]> git.ipfire.org Git - people/ms/ipfire-2.x.git/commitdiff
Import patchset for glibc. glibc-fixes
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 8 Oct 2010 08:12:02 +0000 (10:12 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 8 Oct 2010 08:12:02 +0000 (10:12 +0200)
268 files changed:
lfs/glibc
src/patches/glibc/glibc-2.3.6-fedora.patch [new file with mode: 0644]
src/patches/glibc/glibc-DT_GNU_HASH.patch [new file with mode: 0644]
src/patches/glibc/glibc-MALLOC_CHECK_.patch [new file with mode: 0644]
src/patches/glibc/glibc-Wundef.patch [new file with mode: 0644]
src/patches/glibc/glibc-aio-rh171968.patch [new file with mode: 0644]
src/patches/glibc/glibc-argp-key.patch [new file with mode: 0644]
src/patches/glibc/glibc-argp-vasprintf.patch [new file with mode: 0644]
src/patches/glibc/glibc-argp_usage-NTH.patch [new file with mode: 0644]
src/patches/glibc/glibc-asctime.patch [new file with mode: 0644]
src/patches/glibc/glibc-bindresvport.patch [new file with mode: 0644]
src/patches/glibc/glibc-byteswap.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1051.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1078.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1201.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1228.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1230.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1346.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1548.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1566.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1579.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1774.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1913.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1920.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1925.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1951.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1952.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1955.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1962.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz1978.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2013.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2066.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2072.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2080.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2126.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2153.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2173.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2182.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2226.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2268.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2415.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2418.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2420.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2451.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2498.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2499.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2501.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2502.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2509.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2571.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2592.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2632.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2644.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2680.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2684.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2703.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2766.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2775.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2792.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2821.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2841.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2843.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2892.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2908.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz2998.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz3123.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz3124.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz3155.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz3253.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz3406.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz3451.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz3458.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz3842.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz3855.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz3902.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz394.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz3944.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz3957.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4070.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4074.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4101.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4130.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4344.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4349.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4364.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4405.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4438.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4439.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4514.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4586.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4702.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4745.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4776.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4813.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz4858.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz524.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz5854.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz644.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz6461.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz6719.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz714.patch [new file with mode: 0644]
src/patches/glibc/glibc-bz968.patch [new file with mode: 0644]
src/patches/glibc/glibc-coverity.patch [new file with mode: 0644]
src/patches/glibc/glibc-coverity2.patch [new file with mode: 0644]
src/patches/glibc/glibc-csqrt.patch [new file with mode: 0644]
src/patches/glibc/glibc-ctermid.patch [new file with mode: 0644]
src/patches/glibc/glibc-do_ypcall.patch [new file with mode: 0644]
src/patches/glibc/glibc-doc-fixes.patch [new file with mode: 0644]
src/patches/glibc/glibc-dst-req-static.patch [new file with mode: 0644]
src/patches/glibc/glibc-dtv-is_static.patch [new file with mode: 0644]
src/patches/glibc/glibc-elf64-filebuf-size.patch [new file with mode: 0644]
src/patches/glibc/glibc-euidaccess.patch [new file with mode: 0644]
src/patches/glibc/glibc-fgets-1.patch [new file with mode: 0644]
src/patches/glibc/glibc-gai-leak.patch [new file with mode: 0644]
src/patches/glibc/glibc-gconv-cache-memleak.patch [new file with mode: 0644]
src/patches/glibc/glibc-getconf-a.patch [new file with mode: 0644]
src/patches/glibc/glibc-getdelim-trunc.patch [new file with mode: 0644]
src/patches/glibc/glibc-getent-gethostbyaddr.patch [new file with mode: 0644]
src/patches/glibc/glibc-getent-leak.patch [new file with mode: 0644]
src/patches/glibc/glibc-glob-getlogin_r.patch [new file with mode: 0644]
src/patches/glibc/glibc-hwcap-mask.patch [new file with mode: 0644]
src/patches/glibc/glibc-hypotf.patch [new file with mode: 0644]
src/patches/glibc/glibc-i386-futex-timed-wait.patch [new file with mode: 0644]
src/patches/glibc/glibc-i386-nosegneg.patch [new file with mode: 0644]
src/patches/glibc/glibc-i386-timedrwlock.patch [new file with mode: 0644]
src/patches/glibc/glibc-i686-memset.patch [new file with mode: 0644]
src/patches/glibc/glibc-ia64-lib64.patch [new file with mode: 0644]
src/patches/glibc/glibc-ia64-libm-error.patch [new file with mode: 0644]
src/patches/glibc/glibc-ia64-mcount.patch [new file with mode: 0644]
src/patches/glibc/glibc-ia64-post-upgrade-hack.patch [new file with mode: 0644]
src/patches/glibc/glibc-ia64-shmatt_t.patch [new file with mode: 0644]
src/patches/glibc/glibc-innetgr-leak.patch [new file with mode: 0644]
src/patches/glibc/glibc-innetgr-thread-safety.patch [new file with mode: 0644]
src/patches/glibc/glibc-ld-library-path-DST.patch [new file with mode: 0644]
src/patches/glibc/glibc-ld_debug-conflicts.patch [new file with mode: 0644]
src/patches/glibc/glibc-ldconfig-prelink.patch [new file with mode: 0644]
src/patches/glibc/glibc-lddlibc4.patch [new file with mode: 0644]
src/patches/glibc/glibc-linuxthreads-atomic_h.patch [new file with mode: 0644]
src/patches/glibc/glibc-loadarchive-leak.patch [new file with mode: 0644]
src/patches/glibc/glibc-localealias-leak.patch [new file with mode: 0644]
src/patches/glibc/glibc-madvise-hidden.patch [new file with mode: 0644]
src/patches/glibc/glibc-nan.patch [new file with mode: 0644]
src/patches/glibc/glibc-nis+-batch.patch [new file with mode: 0644]
src/patches/glibc/glibc-nis+-batch2.patch [new file with mode: 0644]
src/patches/glibc/glibc-nis+-findserver.patch [new file with mode: 0644]
src/patches/glibc/glibc-nis+-getenv.patch [new file with mode: 0644]
src/patches/glibc/glibc-nis+-getnames.patch [new file with mode: 0644]
src/patches/glibc/glibc-nis+-leaks.patch [new file with mode: 0644]
src/patches/glibc/glibc-nis+-leaks2.patch [new file with mode: 0644]
src/patches/glibc/glibc-nis+-parent.patch [new file with mode: 0644]
src/patches/glibc/glibc-nis+.patch [new file with mode: 0644]
src/patches/glibc/glibc-nis-getservbyname.patch [new file with mode: 0644]
src/patches/glibc/glibc-nis-publickey.patch [new file with mode: 0644]
src/patches/glibc/glibc-nis_leaf_of_r-0.patch [new file with mode: 0644]
src/patches/glibc/glibc-nonnull.patch [new file with mode: 0644]
src/patches/glibc/glibc-nptl-cancel-init.patch [new file with mode: 0644]
src/patches/glibc/glibc-nptl-check.patch [new file with mode: 0644]
src/patches/glibc/glibc-nptl-fork-cancel.patch [new file with mode: 0644]
src/patches/glibc/glibc-nptl-fork-getpid.patch [new file with mode: 0644]
src/patches/glibc/glibc-nptl-futex-wait.patch [new file with mode: 0644]
src/patches/glibc/glibc-nptl-setxid-2.patch [new file with mode: 0644]
src/patches/glibc/glibc-nptl-setxid.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-EINTR.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-LFS-logging.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-SIGHUP-disabled-cache.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-SIGHUP.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-addinitgroups.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-auto-propagate.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-db-checker.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-debug-verbose.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-fallocate.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-getpw_r-retry.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-hst-noalias.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-max-db-size.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-msync.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-paranoia.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-stat64.patch [new file with mode: 0644]
src/patches/glibc/glibc-nscd-stats.patch [new file with mode: 0644]
src/patches/glibc/glibc-nsswitch_conf.patch [new file with mode: 0644]
src/patches/glibc/glibc-obstack_h-typo.patch [new file with mode: 0644]
src/patches/glibc/glibc-ppc-assume.patch [new file with mode: 0644]
src/patches/glibc/glibc-ppc-fegetround.patch [new file with mode: 0644]
src/patches/glibc/glibc-ppc-libSegFault.patch [new file with mode: 0644]
src/patches/glibc/glibc-ppc-strncmp.patch [new file with mode: 0644]
src/patches/glibc/glibc-prelink-dynamic-weak.patch [new file with mode: 0644]
src/patches/glibc/glibc-printf-string-len.patch [new file with mode: 0644]
src/patches/glibc/glibc-pthread_getattr_np.patch [new file with mode: 0644]
src/patches/glibc/glibc-quota_h.patch [new file with mode: 0644]
src/patches/glibc/glibc-readonly-area.patch [new file with mode: 0644]
src/patches/glibc/glibc-regex_h-STDC.patch [new file with mode: 0644]
src/patches/glibc/glibc-resolv-send_vc.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh168266.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh178934.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh184086.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh190259.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh191464.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh192072.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh193631.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh193873.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh194321.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh197790.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh197932.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh201748.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh201826.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh202991.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh203237.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh203728.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh203915.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh204122.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh205113.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh206483.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh206639.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh207928.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh208203.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh210748-workaround.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh211116.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh215572.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh218782.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh218802.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh219145.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh220621.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh225315.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh227016.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh228103.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh228697.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh230168.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh230197.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh233460.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh235229.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh237711.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh238431.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh247788.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh248281.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh254115.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh339821.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh346321.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh385601.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh403231.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh405781.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh428859.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh434601.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh437571.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh455360.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh461481.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh464146.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh467309.patch [new file with mode: 0644]
src/patches/glibc/glibc-rh470781.patch [new file with mode: 0644]
src/patches/glibc/glibc-rtkaio-update.patch [new file with mode: 0644]
src/patches/glibc/glibc-s390-setjmp.patch [new file with mode: 0644]
src/patches/glibc/glibc-scalb-namespace.patch [new file with mode: 0644]
src/patches/glibc/glibc-sched_getaffinity.patch [new file with mode: 0644]
src/patches/glibc/glibc-sem_timedwait.patch [new file with mode: 0644]
src/patches/glibc/glibc-sigwait-EINTR.patch [new file with mode: 0644]
src/patches/glibc/glibc-sockatmark.patch [new file with mode: 0644]
src/patches/glibc/glibc-stdio-put-error.patch [new file with mode: 0644]
src/patches/glibc/glibc-strtod--0.patch [new file with mode: 0644]
src/patches/glibc/glibc-strtod.patch [new file with mode: 0644]
src/patches/glibc/glibc-strxfrm.patch [new file with mode: 0644]
src/patches/glibc/glibc-sysconf-intel-caches.patch [new file with mode: 0644]
src/patches/glibc/glibc-tgmath-type.patch [new file with mode: 0644]
src/patches/glibc/glibc-tls-model-ie.patch [new file with mode: 0644]
src/patches/glibc/glibc-tst-initializers1.patch [new file with mode: 0644]
src/patches/glibc/glibc-tst-signal7.patch [new file with mode: 0644]
src/patches/glibc/glibc-tzdata-update.patch [new file with mode: 0644]
src/patches/glibc/glibc-wcstol-internal.patch [new file with mode: 0644]
src/patches/glibc/glibc-x86_64-gas-workaround.patch [new file with mode: 0644]
src/patches/glibc/glibc-x86_64-pthread_once-align.patch [new file with mode: 0644]
src/patches/glibc/glibc-xtrace-options.patch [new file with mode: 0644]

index 82394a2e990e49aff4eb0cad6de8fd7031ec59b5..7aa58a96a98d1a62c392d0abdb27c9798f8d7616 100644 (file)
--- a/lfs/glibc
+++ b/lfs/glibc
@@ -103,6 +103,10 @@ ifeq "$(ROOT)" ""
        cd $(DIR_APP) && sed -i 's|libs -o|libs -L/usr/lib -Wl,-dynamic-linker=/lib/ld-linux.so.2 -o|' \
                scripts/test-installation.pl
 endif
+
+       cd $(DIR_APP) && for i in $(DIR_SRC)/src/patches/glibc/*; do \
+               patch -Np1 < $${i}; done
+
        cd $(DIR_SRC)/glibc-build && $(DIR_APP)/configure $(EXTRA_CONFIG)
 
 ifeq "$(ROOT)" ""
diff --git a/src/patches/glibc/glibc-2.3.6-fedora.patch b/src/patches/glibc/glibc-2.3.6-fedora.patch
new file mode 100644 (file)
index 0000000..25be9a9
--- /dev/null
@@ -0,0 +1,2618 @@
+--- glibc-2.3.6/ChangeLog.15   16 Feb 2005 07:35:41 -0000      1.1.2.1
++++ glibc-2.3.6-fedora/ChangeLog.15    18 Feb 2005 02:00:20 -0000      1.1.4.3
+@@ -512,6 +512,14 @@
+ 2004-11-26  Jakub Jelinek  <jakub@redhat.com>
++      * posix/Makefile (generated: Add getconf.speclist.
++      ($(inst_libexecdir)/getconf): Use getconf.speclist instead of
++      getconf output.
++      ($(objpfx)getconf.speclist): New rule.
++      * posix/getconf.speclist.h: New file.
++
++2004-11-26  Jakub Jelinek  <jakub@redhat.com>
++
+       * posix/Makefile (install-others): Add $(inst_libexecdir)/getconf.
+       (CFLAGS-sysconf.c): Add -D_GETCONF_DIR.
+       (CFLAGS-getconf.c): New.
+@@ -1103,6 +1111,16 @@
+       * sysdeps/generic/tempname.c (__path_search): Add missing argument
+       TRY_TMPDIR.
++2004-11-02  Jakub Jelinek  <jakub@redhat.com>
++
++      * include/features.h (__USE_FORTIFY_LEVEL): Also set for Red Hat
++      GCC 3.4.x-RH >= 3.4.2-8.
++      * libio/bits/features.h (printf, fprintf, vprintf, vfprintf): For
++      GCC 3.4.x-RH use __builtin___{,v}{,f}printf_chk instead of
++      __{,v}{,f}printf_chk.
++      * debug/tst-chk1.c (do_test): Deal with GCC 3.4.x-RH not
++      being able to recognize subobjects.
++
+ 2004-10-31  Mariusz Mazur <mmazur@kernel.pl>
+       * sysdeps/unix/sysv/linux/alpha/setregid.c: New file.
+@@ -1398,6 +1416,11 @@
+       * posix/execvp.c (execvp): Also ignore ENODEV and ETIMEDOUT errno
+       values.
++2004-10-20  Jakub Jelinek  <jakub@redhat.com>
++
++      * sysdeps/unix/sysv/linux/readonly-area.c (__readonly_area): If /proc
++      is not mounted, return 1.
++
+ 2004-10-20  Roland McGrath  <roland@redhat.com>
+       * Makeconfig ($(common-objpfx)shlib-versions.v.i): Check also
+@@ -1470,6 +1493,11 @@
+       * debug/catchsegv.sh: Update copyright year.
+       Use mktemp to create segv_output file.
++2004-10-19  Jakub Jelinek  <jakub@redhat.com>
++
++      * include/features.h (__USE_FORTIFY_LEVEL): Enable even with
++      Red Hat gcc4 4.0.0 and above.
++
+ 2004-10-18  Jakub Jelinek  <jakub@redhat.com>
+       * elf/dl-libc.c (__libc_dlsym_private, __libc_register_dl_open_hook):
+@@ -3182,6 +3210,23 @@
+       before return type.
+       * locale/localename.c (__current_locale_name): Likewise.
++2004-08-31  Jakub Jelinek  <jakub@redhat.com>
++
++      * elf/ldconfig.c (parse_conf): Add prefix argument, prepend it
++      before arguments to add_dir and pass to parse_conf_include.
++      (parse_conf_include): Add prefix argument, pass it down to
++      parse_conf.
++      (main): Call arch_startup.  Adjust parse_conf caller.
++      Call add_arch_dirs.
++      * sysdeps/generic/dl-cache.h (arch_startup, add_arch_dirs): Define.
++      * sysdeps/unix/sysv/linux/i386/dl-cache.h: New file.
++      * sysdeps/unix/sysv/linux/ia64/dl-cache.h (EMUL_HACK, arch_startup,
++      add_arch_dirs): Define.
++      * sysdeps/unix/sysv/linux/ia64/ldd-rewrite.sed: Prepend
++      /emul/ia32-linux before the 32-bit ld.so pathname.
++      * sysdeps/unix/sysv/linux/ia64/dl-procinfo.c: New file.
++      * sysdeps/unix/sysv/linux/ia64/dl-procinfo.h: New file.
++
+ 2004-08-30  Roland McGrath  <roland@frob.com>
+       * scripts/extract-abilist.awk: If `lastversion' variable defined, omit
+--- glibc-2.3.6/csu/elf-init.c 16 Aug 2004 04:51:00 -0000      1.3
++++ glibc-2.3.6-fedora/csu/elf-init.c  22 Sep 2004 21:20:47 -0000      1.3.2.1
+@@ -44,6 +44,24 @@ extern void (*__init_array_start []) (vo
+ extern void (*__init_array_end []) (void) attribute_hidden;
+ extern void (*__fini_array_start []) (void) attribute_hidden;
+ extern void (*__fini_array_end []) (void) attribute_hidden;
++
++# if defined HAVE_VISIBILITY_ATTRIBUTE \
++     && (defined SHARED || defined LIBC_NONSHARED)
++#  define hidden_undef_2(x) #x
++#  define hidden_undef_1(x) hidden_undef_2 (x)
++#  define hidden_undef(x) \
++  __asm (hidden_undef_1 (ASM_GLOBAL_DIRECTIVE) " " #x); \
++  __asm (".hidden " #x);
++# else
++#  define hidden_undef(x)
++# endif
++
++hidden_undef (__preinit_array_start)
++hidden_undef (__preinit_array_end)
++hidden_undef (__init_array_start)
++hidden_undef (__init_array_end)
++hidden_undef (__fini_array_start)
++hidden_undef (__fini_array_end)
+ #endif
+ /* These function symbols are provided for the .init/.fini section entry
+--- glibc-2.3.6/debug/tst-chk1.c       18 Nov 2004 23:23:17 -0000      1.5
++++ glibc-2.3.6-fedora/debug/tst-chk1.c        19 Nov 2004 00:18:08 -0000      1.1.2.7
+@@ -213,7 +213,7 @@ do_test (void)
+   if (memcmp (a.buf1, "aabcdabcjj", 10))
+     FAIL ();
+-#if __USE_FORTIFY_LEVEL < 2
++#if __USE_FORTIFY_LEVEL < 2 || !__GNUC_PREREQ (4, 0)
+   /* The following tests are supposed to crash with -D_FORTIFY_SOURCE=2
+      and sufficient GCC support, as the string operations overflow
+      from a.buf1 into a.buf2.  */
+@@ -312,7 +312,7 @@ do_test (void)
+   memset (a.buf1 + 9, 'j', l0 + 2);
+   CHK_FAIL_END
+-#if __USE_FORTIFY_LEVEL >= 2
++#if __USE_FORTIFY_LEVEL >= 2 && __GNUC_PREREQ (4, 0)
+ # define O 0
+ #else
+ # define O 1
+--- glibc-2.3.6/elf/dl-support.c       6 Nov 2004 00:24:49 -0000       1.87
++++ glibc-2.3.6-fedora/elf/dl-support.c        10 Nov 2004 09:02:46 -0000      1.84.2.4
+@@ -281,6 +281,11 @@ _dl_non_dynamic_init (void)
+   if (_dl_platform != NULL)
+     _dl_platformlen = strlen (_dl_platform);
++#if defined (__i386__) && !defined (USE_TLS)
++  /* Load libs not using TLS.  */
++  _dl_osversion = 0x20205;
++#endif
++
+   /* Scan for a program header telling us the stack is nonexecutable.  */
+   if (_dl_phdr != NULL)
+     for (uint_fast16_t i = 0; i < _dl_phnum; ++i)
+--- glibc-2.3.6/elf/ldconfig.c 16 Feb 2005 10:29:34 -0000      1.47.4.1
++++ glibc-2.3.6-fedora/elf/ldconfig.c  16 Feb 2005 19:56:52 -0000      1.47.2.1.2.1
+@@ -944,17 +944,19 @@ search_dirs (void)
+ static void parse_conf_include (const char *config_file, unsigned int lineno,
+-                              bool do_chroot, const char *pattern);
++                              const char *prefix, bool do_chroot,
++                              const char *pattern);
+ /* Parse configuration file.  */
+ static void
+-parse_conf (const char *filename, bool do_chroot)
++parse_conf (const char *filename, const char *prefix, bool do_chroot)
+ {
+   FILE *file = NULL;
+   char *line = NULL;
+   const char *canon;
+   size_t len = 0;
+   unsigned int lineno;
++  size_t prefix_len = prefix ? strlen (prefix) : 0;
+   if (do_chroot && opt_chroot)
+     {
+@@ -1015,7 +1017,14 @@ parse_conf (const char *filename, bool d
+         cp += 8;
+         while ((dir = strsep (&cp, " \t")) != NULL)
+           if (dir[0] != '\0')
+-            parse_conf_include (filename, lineno, do_chroot, dir);
++            parse_conf_include (filename, lineno, prefix, do_chroot, dir);
++      }
++      else if (prefix != NULL)
++      {
++        size_t cp_len = strlen (cp);
++        char new_cp [prefix_len + cp_len + 1];
++        memcpy (mempcpy (new_cp, prefix, prefix_len), cp, cp_len + 1);
++        add_dir (new_cp);
+       }
+       else
+       add_dir (cp);
+@@ -1031,7 +1040,7 @@ parse_conf (const char *filename, bool d
+    config files to read.  */
+ static void
+ parse_conf_include (const char *config_file, unsigned int lineno,
+-                  bool do_chroot, const char *pattern)
++                  const char *prefix, bool do_chroot, const char *pattern)
+ {
+   if (opt_chroot && pattern[0] != '/')
+     error (EXIT_FAILURE, 0,
+@@ -1061,7 +1070,7 @@ parse_conf_include (const char *config_f
+     {
+     case 0:
+       for (size_t i = 0; i < gl.gl_pathc; ++i)
+-      parse_conf (gl.gl_pathv[i], false);
++      parse_conf (gl.gl_pathv[i], prefix, false);
+       globfree64 (&gl);
+       break;
+@@ -1101,6 +1110,8 @@ main (int argc, char **argv)
+ {
+   int remaining;
++  arch_startup (argc, argv);
++
+   /* Parse and process arguments.  */
+   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+@@ -1209,12 +1220,14 @@ main (int argc, char **argv)
+   if (!opt_only_cline)
+     {
+-      parse_conf (config_file, true);
++      parse_conf (config_file, NULL, true);
+       /* Always add the standard search paths.  */
+       add_system_dir (SLIBDIR);
+       if (strcmp (SLIBDIR, LIBDIR))
+       add_system_dir (LIBDIR);
++
++      add_arch_dirs (config_file);
+     }
+   search_dirs ();
+--- glibc-2.3.6/elf/rtld.c     6 Apr 2005 02:49:51 -0000       1.339.2.2
++++ glibc-2.3.6-fedora/elf/rtld.c      20 Mar 2005 18:56:00 -0000      1.330.2.10.2.2
+@@ -1116,6 +1116,53 @@ of this helper program; chances are you 
+   ++GL(dl_ns)[LM_ID_BASE]._ns_nloaded;
+   ++GL(dl_load_adds);
++#if defined(__i386__)
++  /* Force non-TLS libraries for glibc 2.0 binaries
++     or if a buggy binary references non-TLS errno or h_errno.  */
++  if (__builtin_expect (main_map->l_info[DT_NUM + DT_THISPROCNUM
++                                         + DT_VERSIONTAGIDX (DT_VERNEED)]
++                        == NULL, 0)
++      && main_map->l_info[DT_DEBUG])
++    GLRO(dl_osversion) = 0x20205;
++  else if ((__builtin_expect (mode, normal) != normal
++          || main_map->l_info[ADDRIDX (DT_GNU_LIBLIST)] == NULL)
++            /* Only binaries have DT_DEBUG dynamic tags...  */
++         && main_map->l_info[DT_DEBUG])
++    {
++      /* Workaround for buggy binaries.  This doesn't handle buggy
++       libraries.  */
++      bool buggy = false;
++      const ElfW(Sym) *symtab = (const void *) D_PTR (main_map,
++                                                      l_info[DT_SYMTAB]);
++      const char *strtab = (const void *) D_PTR (main_map,
++                                                 l_info[DT_STRTAB]);
++      Elf_Symndx symidx;
++      for (symidx = main_map->l_buckets[0x6c994f % main_map->l_nbuckets];
++         symidx != STN_UNDEF;
++         symidx = main_map->l_chain[symidx])
++      {
++        if (__builtin_expect (strcmp (strtab + symtab[symidx].st_name,
++                                      "errno") == 0, 0)
++            && ELFW(ST_TYPE) (symtab[symidx].st_info) != STT_TLS)
++          buggy = true;
++      }
++      for (symidx = main_map->l_buckets[0xe5c992f % main_map->l_nbuckets];
++         symidx != STN_UNDEF;
++         symidx = main_map->l_chain[symidx])
++      {
++        if (__builtin_expect (strcmp (strtab + symtab[symidx].st_name,
++                                      "h_errno") == 0, 0)
++            && ELFW(ST_TYPE) (symtab[symidx].st_info) != STT_TLS)
++          buggy = true;
++      }
++      if (__builtin_expect (buggy, false) && GLRO(dl_osversion) > 0x20401)
++      {
++        GLRO(dl_osversion) = 0x20401;
++        _dl_error_printf ("Incorrectly built binary which accesses errno or h_errno directly. Needs to be fixed.\n");
++      }
++    }
++#endif
++
+   /* If LD_USE_LOAD_BIAS env variable has not been seen, default
+      to not using bias for non-prelinked PIEs and libraries
+      and using it for executables or prelinked PIEs or libraries.  */
+@@ -1255,6 +1302,58 @@ of this helper program; chances are you 
+       }
+     }
++
++#if defined(__i386__) || defined(__alpha__) || (defined(__sparc__) && !defined(__arch64__))
++  /*
++   * Modifications by Red Hat Software
++   *
++   * Deal with the broken binaries from the non-versioned ages of glibc.
++   * If a binary does not have version information enabled, we assume that
++   * it is a glibc 2.0 binary and we load a compatibility library to try to
++   * overcome binary incompatibilities.
++   *                  Blame: gafton@redhat.com
++   */
++#define LIB_NOVERSION "/lib/libNoVersion.so.1"
++
++  if (__builtin_expect (main_map->l_info[DT_NUM + DT_THISPROCNUM
++                                         + DT_VERSIONTAGIDX (DT_VERNEED)]
++                        == NULL, 0)
++      && (main_map->l_info[DT_DEBUG]
++          || !(GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)))
++    {
++      struct stat test_st;
++      int test_fd;
++      int can_load;
++      
++      HP_TIMING_NOW (start);
++         
++/*       _dl_sysdep_message("Loading compatibility library... ", NULL); */
++
++      can_load = 1;
++      test_fd = __open (LIB_NOVERSION, O_RDONLY);
++      if (test_fd < 0) {
++        can_load = 0;
++/*      _dl_sysdep_message(" Can't find " LIB_NOVERSION "\n",  NULL); */
++      } else {
++        if (__fxstat (_STAT_VER, test_fd, &test_st) < 0 || test_st.st_size == 0) {
++            can_load = 0;
++/*          _dl_sysdep_message(" Can't stat " LIB_NOVERSION "\n",  NULL); */
++        }
++      }
++      
++      if (test_fd >= 0) /* open did no fail.. */
++        __close(test_fd); /* avoid fd leaks */
++
++      if (can_load != 0)
++      npreloads += do_preload (LIB_NOVERSION, main_map,
++                               "nonversioned binary");
++        
++      HP_TIMING_NOW (stop);
++      HP_TIMING_DIFF (diff, start, stop);
++      HP_TIMING_ACCUM_NT (load_time, diff);
++    }
++#endif
++
+   if (__builtin_expect (GL(dl_rtld_map).l_next != NULL, 0))
+     {
+       /* Set up PRELOADS with a vector of the preloaded libraries.  */
+--- glibc-2.3.6/elf/tst-tls10.h        17 Apr 2003 19:19:01 -0000      1.1
++++ glibc-2.3.6-fedora/elf/tst-tls10.h 22 Sep 2004 21:20:48 -0000      1.1.2.1
+@@ -1,8 +1,8 @@
+ #include <tls.h>
+ #include <stdlib.h>
+-#if defined USE_TLS && defined HAVE___THREAD \
+-    && defined HAVE_TLS_MODEL_ATTRIBUTE
++#if defined USE_TLS \
++    && (0 || (defined HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE))
+ # define USE_TLS__THREAD
+ struct A
+--- glibc-2.3.6/iconv/iconvconfig.c    6 Apr 2005 00:37:52 -0000       1.21.2.2
++++ glibc-2.3.6-fedora/iconv/iconvconfig.c     3 Mar 2005 16:27:44 -0000       1.19.2.2.2.2
+@@ -1013,6 +1013,34 @@ next_prime (uint32_t seed)
+                               module name offset
+                          (following last entry with step count 0)
+ */
++
++static struct hash_entry *hash_table;
++static size_t hash_size;
++
++/* Function to insert the names.  */
++static void name_insert (const void *nodep, VISIT value, int level)
++{
++  struct name *name;
++  unsigned int idx;
++  unsigned int hval2;
++
++  if (value != leaf && value != postorder)
++    return;
++
++  name = *(struct name **) nodep;
++  idx = name->hashval % hash_size;
++  hval2 = 1 + name->hashval % (hash_size - 2);
++
++  while (hash_table[idx].string_offset != 0)
++    if ((idx += hval2) >= hash_size)
++      idx -= hash_size;
++
++  hash_table[idx].string_offset = strtaboffset (name->strent);
++
++  assert (name->module_idx != -1);
++  hash_table[idx].module_idx = name->module_idx;
++}
++
+ static int
+ write_output (void)
+ {
+@@ -1020,8 +1048,6 @@ write_output (void)
+   char *string_table;
+   size_t string_table_size;
+   struct gconvcache_header header;
+-  struct hash_entry *hash_table;
+-  size_t hash_size;
+   struct module_entry *module_table;
+   char *extra_table;
+   char *cur_extra_table;
+@@ -1034,31 +1060,6 @@ write_output (void)
+   char tmpfname[(output_file == NULL ? sizeof finalname : output_file_len + 1)
+               + strlen (".XXXXXX")];
+-  /* Function to insert the names.  */
+-  auto void
+-  name_insert (const void *nodep, VISIT value, int level)
+-    {
+-      struct name *name;
+-      unsigned int idx;
+-      unsigned int hval2;
+-
+-      if (value != leaf && value != postorder)
+-      return;
+-
+-      name = *(struct name **) nodep;
+-      idx = name->hashval % hash_size;
+-      hval2 = 1 + name->hashval % (hash_size - 2);
+-
+-      while (hash_table[idx].string_offset != 0)
+-      if ((idx += hval2) >= hash_size)
+-        idx -= hash_size;
+-
+-      hash_table[idx].string_offset = strtaboffset (name->strent);
+-
+-      assert (name->module_idx != -1);
+-      hash_table[idx].module_idx = name->module_idx;
+-    }
+-
+   /* Open the output file.  */
+   if (output_file == NULL)
+     {
+--- glibc-2.3.6/include/features.h     18 Feb 2005 00:08:56 -0000      1.36.2.1
++++ glibc-2.3.6-fedora/include/features.h      18 Feb 2005 02:00:22 -0000      1.35.2.4.2.1
+@@ -262,7 +262,13 @@
+ # define __USE_REENTRANT      1
+ #endif
+-#if _FORTIFY_SOURCE > 0 && __GNUC_PREREQ (4, 1) && __OPTIMIZE__ > 0
++#if _FORTIFY_SOURCE > 0 && __OPTIMIZE__ > 0 \
++    && (__GNUC_PREREQ (4, 1) \
++        || (defined __GNUC_RH_RELEASE__ && __GNUC_PREREQ (4, 0)) \
++        || (defined __GNUC_RH_RELEASE__ && __GNUC_PREREQ (3, 4) \
++            && __GNUC_MINOR__ == 4 \
++            && (__GNUC_PATCHLEVEL__ > 2 \
++                || (__GNUC_PATCHLEVEL__ == 2 && __GNUC_RH_RELEASE__ >= 8))))
+ # if _FORTIFY_SOURCE == 1
+ #  define __USE_FORTIFY_LEVEL 1
+ # elif _FORTIFY_SOURCE > 1
+--- glibc-2.3.6/intl/locale.alias      4 Dec 2003 07:57:47 -0000       1.23
++++ glibc-2.3.6-fedora/intl/locale.alias       22 Sep 2004 21:20:53 -0000      1.23.2.1
+@@ -58,8 +58,6 @@ korean               ko_KR.eucKR
+ korean.euc    ko_KR.eucKR
+ ko_KR         ko_KR.eucKR
+ lithuanian      lt_LT.ISO-8859-13
+-no_NO         nb_NO.ISO-8859-1
+-no_NO.ISO-8859-1 nb_NO.ISO-8859-1
+ norwegian       nb_NO.ISO-8859-1
+ nynorsk               nn_NO.ISO-8859-1
+ polish          pl_PL.ISO-8859-2
+--- glibc-2.3.6/libio/stdio.h  18 Oct 2004 04:17:15 -0000      1.79
++++ glibc-2.3.6-fedora/libio/stdio.h   18 Oct 2004 09:58:44 -0000      1.78.2.2
+@@ -142,10 +142,12 @@ typedef _G_fpos64_t fpos64_t;
+ extern struct _IO_FILE *stdin;                /* Standard input stream.  */
+ extern struct _IO_FILE *stdout;               /* Standard output stream.  */
+ extern struct _IO_FILE *stderr;               /* Standard error output stream.  */
++#ifdef __STDC__
+ /* C89/C99 say they're macros.  Make them happy.  */
+ #define stdin stdin
+ #define stdout stdout
+ #define stderr stderr
++#endif
+ __BEGIN_NAMESPACE_STD
+ /* Remove file FILENAME.  */
+--- glibc-2.3.6/libio/bits/stdio2.h    18 Oct 2004 04:17:14 -0000      1.1
++++ glibc-2.3.6-fedora/libio/bits/stdio2.h     2 Nov 2004 13:30:19 -0000       1.1.2.2
+@@ -61,14 +61,25 @@ extern int __vfprintf_chk (FILE *__restr
+ extern int __vprintf_chk (int __flag, __const char *__restrict __format,
+                         _G_va_list __ap);
+-# define printf(...) \
++# if __GNUC_PREREQ (4, 0)
++#  define printf(...) \
+   __printf_chk (__USE_FORTIFY_LEVEL - 1, __VA_ARGS__)
+-# define fprintf(stream, ...) \
++#  define fprintf(stream, ...) \
+   __fprintf_chk (stream, __USE_FORTIFY_LEVEL - 1, __VA_ARGS__)
+-# define vprintf(format, ap) \
++#  define vprintf(format, ap) \
+   __vprintf_chk (__USE_FORTIFY_LEVEL - 1, format, ap)
+-# define vfprintf(stream, format, ap) \
++#  define vfprintf(stream, format, ap) \
+   __vfprintf_chk (stream, __USE_FORTIFY_LEVEL - 1, format, ap)
++# else
++#  define printf(...) \
++  __builtin___printf_chk (__USE_FORTIFY_LEVEL - 1, __VA_ARGS__)
++#  define fprintf(stream, ...) \
++  __builtin___fprintf_chk (stream, __USE_FORTIFY_LEVEL - 1, __VA_ARGS__)
++#  define vprintf(format, ap) \
++  __builtin___vprintf_chk (__USE_FORTIFY_LEVEL - 1, format, ap)
++#  define vfprintf(stream, format, ap) \
++  __builtin___vfprintf_chk (stream, __USE_FORTIFY_LEVEL - 1, format, ap)
++# endif
+ #endif
+--- glibc-2.3.6/linuxthreads/ChangeLog 17 Oct 2005 04:57:37 -0000      1.833.2.4
++++ glibc-2.3.6-fedora/linuxthreads/ChangeLog  17 Oct 2005 05:22:00 -0000      1.817.2.14.2.3
+@@ -764,6 +764,12 @@
+       (pthread_barrierattr_setpshared): Return EINVAL if pshared
+       is neither PTHREAD_PROCESS_PRIVATE nor PTHREAD_PROCESS_SHARED.
++2003-09-02  Jakub Jelinek  <jakub@redhat.com>
++
++      * sysdeps/sparc/tls.h (TLS_TCB_SIZE): If in ld.so and NPTL struct
++      pthread is bigger than struct _pthread_descr_struct, use NPTL struct
++      pthread size.
++
+ 2003-09-02  Ulrich Drepper  <drepper@redhat.com>
+       * sysdeps/unix/sysv/linux/i386/dl-sysdep.h
+@@ -896,6 +902,34 @@
+ 2003-07-22  Jakub Jelinek  <jakub@redhat.com>
++      * sysdeps/alpha/tls.h (TLS_INIT_TCB_SIZE, TLS_TCB_SIZE): Change to 0.
++      (TLS_INIT_TCB_ALIGN, TLS_TCB_ALIGN): Alignment of struct
++      _pthread_descr_struct.
++      (TLS_PRE_TCB_SIZE): Add sizeof (tcbhead_t) and pad to align.
++      If in ld.so and NPTL struct pthread is bigger than struct
++      _pthread_descr_struct, use NPTL struct pthread size.
++      (TLS_TCB_OFFSET): Define.
++      (INSTALL_DTV, INSTALL_NEW_DTV, GET_DTV, TLS_INIT_TP, THREAD_DTV,
++      THREAD_SELF, INIT_THREAD_SELF): Changed to match NPTL tls.h
++      definitions.
++      * sysdeps/i386/tls.h (TLS_TCB_SIZE): If in ld.so and NPTL struct
++      pthread is bigger than struct _pthread_descr_struct, use NPTL struct
++      pthread size.
++      * sysdeps/ia64/tls.h (TLS_PRE_TCB_SIZE): Likewise.
++      * sysdeps/powerpc/tls.h (TLS_PRE_TCB_SIZE): Likewise.
++      * sysdeps/s390/tls.h (TLS_TCB_SIZE): Likewise.
++      * sysdeps/sh/tls.h (TLS_PRE_TCB_SIZE): Likewise.
++      * sysdeps/x86_64/tls.h (TLS_TCB_SIZE): Likewise.
++      * sysdeps/pthread/Makefile (gen-as-const-headers): Add
++      nptl-struct-pthread.sym if nptl tree is present.
++      (before-compile): Add $(common-objpfx)nptl-struct-pthread.h
++      if nptl tree is not present.
++      (common-generated): Add nptl-struct-pthread.h.
++      ($(common-objpfx)nptl-struct-pthread.h): New rule.
++      * sysdeps/pthread/nptl-struct-pthread.sym: New file.
++
++2003-07-22  Jakub Jelinek  <jakub@redhat.com>
++
+       * descr.h (struct _pthread_descr_struct): Provide p_res member
+       even if USE_TLS && HAVE___THREAD.
+       * sysdeps/pthread/res-state.c (__res_state): Return __resp
+--- glibc-2.3.6/linuxthreads/Makefile  16 Feb 2005 11:26:38 -0000      1.96.2.2
++++ glibc-2.3.6-fedora/linuxthreads/Makefile   16 Feb 2005 19:56:54 -0000      1.94.2.3.2.1
+@@ -245,15 +245,18 @@ $(addprefix $(objpfx), \
+   $(filter-out $(tests-static) $(tests-reverse) unload, \
+     $(tests) $(test-srcs))): $(objpfx)libpthread.so \
+                            $(objpfx)libpthread_nonshared.a
+-# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so,
++# $(objpfx)linklibc.so is used instead of $(common-objpfx)libc.so,
+ # since otherwise libpthread.so comes before libc.so when linking.
+ $(addprefix $(objpfx), $(tests-reverse)): \
+-  $(objpfx)../libc.so $(objpfx)libpthread.so \
++  $(objpfx)linklibc.so $(objpfx)libpthread.so \
+   $(objpfx)libpthread_nonshared.a
+ $(objpfx)../libc.so: $(common-objpfx)libc.so ;
+ $(addprefix $(objpfx),$(librt-tests)): $(common-objpfx)rt/librt.so
+ $(objpfx)unload: $(common-objpfx)dlfcn/libdl.so
+ $(objpfx)unload.out: $(objpfx)libpthread.so $(objpfx)libpthread_nonshared.a
++$(objpfx)linklibc.so: $(common-objpfx)libc.so
++      ln -s ../libc.so $@
++generated += libclink.so
+ else
+ $(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a
+ $(addprefix $(objpfx),$(librt-tests)): $(common-objpfx)rt/librt.a
+--- glibc-2.3.6/linuxthreads/cancel.c  22 Feb 2003 00:55:21 -0000      1.23
++++ glibc-2.3.6-fedora/linuxthreads/cancel.c   22 Sep 2004 21:20:55 -0000      1.23.2.1
+@@ -230,5 +230,6 @@ void __pthread_perform_cleanup(char *cur
+     }
+   /* And the TSD which needs special help.  */
++  THREAD_SETMEM (self, p_cancelstate, PTHREAD_CANCEL_DISABLE);
+   __libc_thread_freeres ();
+ }
+--- glibc-2.3.6/linuxthreads/lockfile.c        18 Dec 2002 01:16:46 -0000      1.10
++++ glibc-2.3.6-fedora/linuxthreads/lockfile.c 22 Sep 2004 21:20:55 -0000      1.10.2.1
+@@ -74,7 +74,11 @@ __fresetlockfiles (void)
+   __pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE_NP);
+   for (i = _IO_iter_begin(); i != _IO_iter_end(); i = _IO_iter_next(i))
+-    __pthread_mutex_init (_IO_iter_file(i)->_lock, &attr);
++    {
++      _IO_lock_t *_lock = _IO_iter_file(i)->_lock;
++      if (_lock)
++      __pthread_mutex_init (_lock, &attr);
++    }
+   __pthread_mutexattr_destroy (&attr);
+--- glibc-2.3.6/linuxthreads/semaphore.h       17 Apr 2004 23:01:39 -0000      1.13
++++ glibc-2.3.6-fedora/linuxthreads/semaphore.h        22 Sep 2004 21:20:55 -0000      1.13.2.1
+@@ -21,6 +21,7 @@
+ # define __need_timespec
+ # include <time.h>
+ #endif
++#include <bits/pthreadtypes.h>
+ #ifndef _PTHREAD_DESCR_DEFINED
+ /* Thread descriptors.  Needed for `sem_t' definition.  */
+--- glibc-2.3.6/linuxthreads/tst-tls1.h        2 Sep 2003 00:29:30 -0000       1.1
++++ glibc-2.3.6-fedora/linuxthreads/tst-tls1.h 22 Sep 2004 21:20:55 -0000      1.1.2.1
+@@ -2,7 +2,7 @@
+ #include <stdlib.h>
+ #include <tls.h>
+-#if USE_TLS && HAVE___THREAD
++#if USE_TLS && (0 || HAVE___THREAD)
+ struct tls_obj
+ {
+--- glibc-2.3.6/linuxthreads/sysdeps/alpha/tls.h       30 Jan 2003 21:03:40 -0000      1.5
++++ glibc-2.3.6-fedora/linuxthreads/sysdeps/alpha/tls.h        22 Sep 2004 21:20:55 -0000      1.5.2.1
+@@ -53,54 +53,76 @@ typedef struct
+ #  include <sysdep.h>
+ /* This is the size of the initial TCB.  */
+-#  define TLS_INIT_TCB_SIZE   sizeof (tcbhead_t)
++#  define TLS_INIT_TCB_SIZE   0
+ /* Alignment requirements for the initial TCB.  */
+-#  define TLS_INIT_TCB_ALIGN  __alignof__ (tcbhead_t)
++#  define TLS_INIT_TCB_ALIGN  __alignof__ (struct _pthread_descr_struct)
+ /* This is the size of the TCB.  */
+-#  define TLS_TCB_SIZE                sizeof (tcbhead_t)
++#  define TLS_TCB_SIZE                0
+ /* Alignment requirements for the TCB.  */
+-#  define TLS_TCB_ALIGN               __alignof__ (tcbhead_t)
++#  define TLS_TCB_ALIGN               __alignof__ (struct _pthread_descr_struct)
+ /* This is the size we need before TCB.  */
+-#  define TLS_PRE_TCB_SIZE    sizeof (struct _pthread_descr_struct)
++#  ifndef IS_IN_rtld
++#   define TLS_PRE_TCB_SIZE \
++  (sizeof (struct _pthread_descr_struct)                              \
++   + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
++#  else
++#   include <nptl-struct-pthread.h>
++#   define TLS_PRE_TCB_SIZE \
++  ((sizeof (struct _pthread_descr_struct) > NPTL_STRUCT_PTHREAD_SIZE  \
++    ? sizeof (struct _pthread_descr_struct) : NPTL_STRUCT_PTHREAD_SIZE)       \
++   + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
++#  endif
+ /* The DTV is allocated at the TP; the TCB is placed elsewhere.  */
+ #  define TLS_DTV_AT_TP 1
++/* The following assumes that TP (R2 or R13) points to the end of the
++   TCB + 0x7000 (per the ABI).  This implies that TCB address is
++   TP - 0x7000.  As we define TLS_DTV_AT_TP we can
++   assume that the pthread struct is allocated immediately ahead of the
++   TCB.  This implies that the pthread_descr address is
++   TP - (TLS_PRE_TCB_SIZE + 0x7000).  */
++/* ??? PPC uses offset 0x7000; seems like a good idea for alpha too,
++   but binutils not yet changed to match.  */
++#  define TLS_TCB_OFFSET 0
++
+ /* Install the dtv pointer.  The pointer passed is to the element with
+    index -1 which contain the length.  */
+ #  define INSTALL_DTV(TCBP, DTVP) \
+-  (((tcbhead_t *) (TCBP))->dtv = (DTVP) + 1)
++  (((tcbhead_t *) (TCBP))[-1].dtv = (DTVP) + 1)
+ /* Install new dtv for current thread.  */
+ #  define INSTALL_NEW_DTV(DTV) \
+-  (((tcbhead_t *)__builtin_thread_pointer ())->dtv = (DTV))
++  (THREAD_DTV() = (DTV))
+ /* Return dtv of given thread descriptor.  */
+ #  define GET_DTV(TCBP) \
+-  (((tcbhead_t *) (TCBP))->dtv)
++  (((tcbhead_t *) (TCBP))[-1].dtv)
+ /* Code to initially initialize the thread pointer.  This might need
+    special attention since 'errno' is not yet available and if the
+    operation can cause a failure 'errno' must not be touched.  */
+ # define TLS_INIT_TP(TCBP, SECONDCALL) \
+-  (__builtin_set_thread_pointer (TCBP), 0)
++  (__builtin_set_thread_pointer ((void *) (TCBP) + TLS_TCB_OFFSET), NULL)
+ /* Return the address of the dtv for the current thread.  */
+ #  define THREAD_DTV() \
+-  (((tcbhead_t *)__builtin_thread_pointer ())->dtv)
++  (((tcbhead_t *) (__builtin_thread_pointer () - TLS_TCB_OFFSET))[-1].dtv)
+ /* Return the thread descriptor for the current thread.  */
+ #  undef THREAD_SELF
+ #  define THREAD_SELF \
+-  ((pthread_descr)__builtin_thread_pointer () - 1)
++  ((pthread_descr) (__builtin_thread_pointer () \
++                  - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE))
+ #  undef INIT_THREAD_SELF
+ #  define INIT_THREAD_SELF(DESCR, NR) \
+-  __builtin_set_thread_pointer ((struct _pthread_descr_struct *)(DESCR) + 1)
++  __builtin_set_thread_pointer ((char *)(DESCR) \
++                              + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)
+ /* Get the thread descriptor definition.  */
+ #  include <linuxthreads/descr.h>
+--- glibc-2.3.6/linuxthreads/sysdeps/i386/tls.h        19 Oct 2004 05:12:58 -0000      1.37
++++ glibc-2.3.6-fedora/linuxthreads/sysdeps/i386/tls.h 20 Oct 2004 10:47:17 -0000      1.35.2.4
+@@ -81,7 +81,14 @@ typedef struct
+ #  define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
+ /* This is the size of the TCB.  */
+-#  define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
++#  ifndef IS_IN_rtld
++#   define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
++#  else
++#   include <nptl-struct-pthread.h>
++#   define TLS_TCB_SIZE \
++  (sizeof (struct _pthread_descr_struct) > NPTL_STRUCT_PTHREAD_SIZE   \
++   ? sizeof (struct _pthread_descr_struct) : NPTL_STRUCT_PTHREAD_SIZE)
++#  endif
+ /* Alignment requirements for the TCB.  */
+ #  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+--- glibc-2.3.6/linuxthreads/sysdeps/ia64/tls.h        8 Jul 2004 21:20:57 -0000       1.9
++++ glibc-2.3.6-fedora/linuxthreads/sysdeps/ia64/tls.h 22 Sep 2004 21:20:55 -0000      1.9.2.1
+@@ -60,7 +60,14 @@ typedef struct
+ #  define TLS_TCB_SIZE sizeof (tcbhead_t)
+ /* This is the size we need before TCB.  */
+-#  define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct)
++#  ifndef IS_IN_rtld
++#   define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct)
++#  else
++#   include <nptl-struct-pthread.h>
++#   define TLS_PRE_TCB_SIZE \
++  (sizeof (struct _pthread_descr_struct) > NPTL_STRUCT_PTHREAD_SIZE   \
++   ? sizeof (struct _pthread_descr_struct) : NPTL_STRUCT_PTHREAD_SIZE)
++#  endif
+ /* Alignment requirements for the TCB.  */
+ #  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+--- glibc-2.3.6/linuxthreads/sysdeps/powerpc/tls.h     9 Apr 2004 19:09:42 -0000       1.8
++++ glibc-2.3.6-fedora/linuxthreads/sysdeps/powerpc/tls.h      22 Sep 2004 21:20:55 -0000      1.8.2.1
+@@ -64,11 +64,19 @@ typedef struct
+ #  define TLS_TCB_ALIGN               __alignof__ (struct _pthread_descr_struct)
+ /* This is the size we need before TCB.  */
+-#  define TLS_PRE_TCB_SIZE \
++#  ifndef IS_IN_rtld
++#   define TLS_PRE_TCB_SIZE \
+   (sizeof (struct _pthread_descr_struct)                                    \
+    + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
++#  else
++#   include <nptl-struct-pthread.h>
++#   define TLS_PRE_TCB_SIZE \
++  ((sizeof (struct _pthread_descr_struct) > NPTL_STRUCT_PTHREAD_SIZE        \
++    ? sizeof (struct _pthread_descr_struct) : NPTL_STRUCT_PTHREAD_SIZE)             \
++   + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
++#  endif
+-/* The following assumes that TP (R2 or R13) is points to the end of the
++/* The following assumes that TP (R2 or R13) points to the end of the
+    TCB + 0x7000 (per the ABI).  This implies that TCB address is
+    TP - 0x7000.  As we define TLS_DTV_AT_TP we can
+    assume that the pthread_descr is allocated immediately ahead of the
+--- glibc-2.3.6/linuxthreads/sysdeps/pthread/Makefile  14 Aug 2003 00:14:22 -0000      1.7
++++ glibc-2.3.6-fedora/linuxthreads/sysdeps/pthread/Makefile   22 Sep 2004 21:20:56 -0000      1.7.2.1
+@@ -12,3 +12,15 @@ endif
+ ifeq ($(subdir),posix)
+ CFLAGS-confstr.c += -DLIBPTHREAD_VERSION="\"$(shell sed 's/\(.*\) by .*/\1/' ../linuxthreads/Banner)\""
+ endif
++
++ifeq ($(subdir),csu)
++# Find out the size of NPTL struct pthread
++ifneq (,$(wildcard $(..)nptl/descr.h))
++gen-as-const-headers += nptl-struct-pthread.sym
++else
++before-compile += $(common-objpfx)nptl-struct-pthread.h
++common-generated += nptl-struct-pthread.h
++$(common-objpfx)nptl-struct-pthread.h:
++      @echo '#define NPTL_STRUCT_PTHREAD_SIZE 0' > $@
++endif
++endif
+--- glibc-2.3.6/linuxthreads/sysdeps/pthread/nptl-struct-pthread.sym 1 Jan 1970 00:00:00 -0000
++++ glibc-2.3.6-fedora/linuxthreads/sysdeps/pthread/nptl-struct-pthread.sym    22 Sep 2004 21:20:56 -0000      1.1.2.1
+@@ -0,0 +1,13 @@
++#ifdef HAVE_TLS_SUPPORT
++# ifndef HAVE_FORCED_UNWIND
++#  define HAVE_FORCED_UNWIND 1
++# endif
++# define __need_struct_pthread_size
++# include <nptl/descr.h>
++#endif
++
++--
++
++#ifdef HAVE_TLS_SUPPORT
++NPTL_STRUCT_PTHREAD_SIZE      sizeof (struct pthread)
++#endif
+--- glibc-2.3.6/linuxthreads/sysdeps/s390/tls.h        30 Jan 2003 18:34:11 -0000      1.3
++++ glibc-2.3.6-fedora/linuxthreads/sysdeps/s390/tls.h 22 Sep 2004 21:20:56 -0000      1.3.2.1
+@@ -72,7 +72,14 @@ typedef struct
+ #  define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
+ /* This is the size of the TCB.  */
+-#  define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
++#  ifndef IS_IN_rtld
++#   define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
++#  else
++#   include <nptl-struct-pthread.h>
++#   define TLS_TCB_SIZE \
++  (sizeof (struct _pthread_descr_struct) > NPTL_STRUCT_PTHREAD_SIZE   \
++   ? sizeof (struct _pthread_descr_struct) : NPTL_STRUCT_PTHREAD_SIZE)
++#  endif
+ /* Alignment requirements for the TCB.  */
+ #  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+--- glibc-2.3.6/linuxthreads/sysdeps/sh/tls.h  2 Mar 2003 11:44:20 -0000       1.9
++++ glibc-2.3.6-fedora/linuxthreads/sysdeps/sh/tls.h   22 Sep 2004 21:20:57 -0000      1.9.2.1
+@@ -64,7 +64,14 @@ typedef struct
+ #  define TLS_TCB_SIZE sizeof (tcbhead_t)
+ /* This is the size we need before TCB.  */
+-#  define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct)
++#  ifndef IS_IN_rtld
++#   define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct)
++#  else
++#   include <nptl-struct-pthread.h>
++#   define TLS_PRE_TCB_SIZE \
++  (sizeof (struct _pthread_descr_struct) > NPTL_STRUCT_PTHREAD_SIZE   \
++   ? sizeof (struct _pthread_descr_struct) : NPTL_STRUCT_PTHREAD_SIZE)
++#  endif
+ /* Alignment requirements for the TCB.  */
+ #  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+--- glibc-2.3.6/linuxthreads/sysdeps/sparc/tls.h       4 Feb 2003 20:41:02 -0000       1.3
++++ glibc-2.3.6-fedora/linuxthreads/sysdeps/sparc/tls.h        22 Sep 2004 21:20:57 -0000      1.3.2.1
+@@ -64,7 +64,14 @@ typedef struct
+ #  define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
+ /* This is the size of the TCB.  */
+-#  define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
++#  ifndef IS_IN_rtld
++#   define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
++#  else
++#   include <nptl-struct-pthread.h>
++#   define TLS_TCB_SIZE \
++  (sizeof (struct _pthread_descr_struct) > NPTL_STRUCT_PTHREAD_SIZE   \
++   ? sizeof (struct _pthread_descr_struct) : NPTL_STRUCT_PTHREAD_SIZE)
++#  endif
+ /* Alignment requirements for the TCB.  */
+ #  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+--- glibc-2.3.6/linuxthreads/sysdeps/x86_64/tls.h      18 Apr 2004 02:32:25 -0000      1.6
++++ glibc-2.3.6-fedora/linuxthreads/sysdeps/x86_64/tls.h       22 Sep 2004 21:20:57 -0000      1.6.2.1
+@@ -66,7 +66,14 @@ typedef struct
+ #  define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
+ /* This is the size of the TCB.  */
+-#  define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
++#  ifndef IS_IN_rtld
++#   define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
++#  else
++#   include <nptl-struct-pthread.h>
++#   define TLS_TCB_SIZE \
++  (sizeof (struct _pthread_descr_struct) > NPTL_STRUCT_PTHREAD_SIZE   \
++   ? sizeof (struct _pthread_descr_struct) : NPTL_STRUCT_PTHREAD_SIZE)
++#  endif
+ /* Alignment requirements for the TCB.  */
+ #  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+--- glibc-2.3.6/locale/iso-4217.def    18 Jul 2005 01:47:31 -0000      1.15.4.1
++++ glibc-2.3.6-fedora/locale/iso-4217.def     18 Jul 2005 04:40:54 -0000      1.15.2.1.2.1
+@@ -8,6 +8,7 @@
+  *
+  * !!! The list has to be sorted !!!
+  */
++DEFINE_INT_CURR("ADP")                /* Andorran Peseta -> EUR  */
+ DEFINE_INT_CURR("AED")                /* United Arab Emirates Dirham  */
+ DEFINE_INT_CURR("AFA")                /* Afghanistan Afgani  */
+ DEFINE_INT_CURR("ALL")                /* Albanian Lek  */
+@@ -15,12 +16,14 @@ DEFINE_INT_CURR("AMD")             /* Armenia Dram 
+ DEFINE_INT_CURR("ANG")                /* Netherlands Antilles  */
+ DEFINE_INT_CURR("AOA")                /* Angolan Kwanza  */
+ DEFINE_INT_CURR("ARS")                /* Argentine Peso  */
++DEFINE_INT_CURR("ATS")                /* Austrian Schilling -> EUR  */
+ DEFINE_INT_CURR("AUD")                /* Australian Dollar  */
+ DEFINE_INT_CURR("AWG")                /* Aruba Guilder  */
+ DEFINE_INT_CURR("AZM")                /* Azerbaijan Manat  */
+ DEFINE_INT_CURR("BAK")                /* Bosnian and Herzegovina Convertible Mark  */
+ DEFINE_INT_CURR("BBD")                /* Barbados Dollar  */
+ DEFINE_INT_CURR("BDT")                /* Bangladesh Taka  */
++DEFINE_INT_CURR("BEF")                /* Belgian Franc -> EUR  */
+ DEFINE_INT_CURR("BGL")                /* Bulgarian Lev  */
+ DEFINE_INT_CURR("BHD")                /* Bahraini Dinar  */
+ DEFINE_INT_CURR("BIF")                /* Burundi Franc  */
+@@ -45,6 +48,7 @@ DEFINE_INT_CURR("CUP")               /* Cuban Peso  *
+ DEFINE_INT_CURR("CVE")                /* Cape Verde Escudo  */
+ DEFINE_INT_CURR("CYP")                /* Cypriot Pound  */
+ DEFINE_INT_CURR("CZK")                /* Czech Koruna  */
++DEFINE_INT_CURR("DEM")                /* German Mark -> EUR  */
+ DEFINE_INT_CURR("DJF")                /* Djibouti Franc  */
+ DEFINE_INT_CURR("DKK")                /* Danish Krone (Faroe Islands, Greenland)  */
+ DEFINE_INT_CURR("DOP")                /* Dominican Republic  */
+@@ -52,16 +56,20 @@ DEFINE_INT_CURR("DZD")             /* Algerian Dina
+ DEFINE_INT_CURR("EEK")                /* Estonian Kroon  */
+ DEFINE_INT_CURR("EGP")                /* Egyptian Pound  */
+ DEFINE_INT_CURR("ERN")                /* Eritrean Nakfa  */
++DEFINE_INT_CURR("ESP")                /* Spanish Peseta -> EUR  */
+ DEFINE_INT_CURR("ETB")                /* Ethiopian Birr  */
+ DEFINE_INT_CURR("EUR")                /* European Union Euro  */
++DEFINE_INT_CURR("FIM")                /* Finnish Markka -> EUR  */
+ DEFINE_INT_CURR("FJD")                /* Fiji Dollar  */
+ DEFINE_INT_CURR("FKP")                /* Falkland Islands Pound (Malvinas)  */
++DEFINE_INT_CURR("FRF")                /* French Franc -> EUR  */
+ DEFINE_INT_CURR("GBP")                /* British Pound  */
+ DEFINE_INT_CURR("GEL")                /* Georgia Lari  */
+ DEFINE_INT_CURR("GHC")                /* Ghana Cedi  */
+ DEFINE_INT_CURR("GIP")                /* Gibraltar Pound  */
+ DEFINE_INT_CURR("GMD")                /* Gambian Dalasi  */
+ DEFINE_INT_CURR("GNF")                /* Guinea Franc  */
++DEFINE_INT_CURR("GRD")                /* Greek Drachma -> EUR  */
+ DEFINE_INT_CURR("GTQ")                /* Guatemala Quetzal  */
+ DEFINE_INT_CURR("GYD")                /* Guyana Dollar  */
+ DEFINE_INT_CURR("HKD")                /* Hong Kong Dollar  */
+@@ -70,12 +78,14 @@ DEFINE_INT_CURR("HRK")             /* Croatia Kuna 
+ DEFINE_INT_CURR("HTG")                /* Haiti Gourde  */
+ DEFINE_INT_CURR("HUF")                /* Hungarian Forint  */
+ DEFINE_INT_CURR("IDR")                /* Indonesia Rupiah  */
++DEFINE_INT_CURR("IEP")                /* Irish Pound -> EUR  */
+ DEFINE_INT_CURR("ILS")                /* Israeli Shekel  */
+ DEFINE_INT_CURR("IMP")                /* Isle of Man Pounds  */
+ DEFINE_INT_CURR("INR")                /* Indian Rupee (Bhutan)  */
+ DEFINE_INT_CURR("IQD")                /* Iraqi Dinar  */
+ DEFINE_INT_CURR("IRR")                /* Iranian Rial  */
+ DEFINE_INT_CURR("ISK")                /* Iceland Krona  */
++DEFINE_INT_CURR("ITL")                /* Italian Lira -> EUR  */
+ DEFINE_INT_CURR("JMD")                /* Jamaican Dollar  */
+ DEFINE_INT_CURR("JOD")                /* Jordanian Dinar  */
+ DEFINE_INT_CURR("JPY")                /* Japanese Yen  */
+@@ -94,6 +104,7 @@ DEFINE_INT_CURR("LKR")              /* Sri Lankan Ru
+ DEFINE_INT_CURR("LRD")                /* Liberian Dollar  */
+ DEFINE_INT_CURR("LSL")                /* Lesotho Maloti  */
+ DEFINE_INT_CURR("LTL")                /* Lithuanian Litas  */
++DEFINE_INT_CURR("LUF")                /* Luxembourg Franc -> EUR  */
+ DEFINE_INT_CURR("LVL")                /* Latvia Lat  */
+ DEFINE_INT_CURR("LYD")                /* Libyan Arab Jamahiriya Dinar  */
+ DEFINE_INT_CURR("MAD")                /* Moroccan Dirham  */
+@@ -114,6 +125,7 @@ DEFINE_INT_CURR("MZM")             /* Mozambique Me
+ DEFINE_INT_CURR("NAD")                /* Namibia Dollar  */
+ DEFINE_INT_CURR("NGN")                /* Nigeria Naira  */
+ DEFINE_INT_CURR("NIO")                /* Nicaragua Cordoba Oro  */
++DEFINE_INT_CURR("NLG")                /* Netherlands Guilder -> EUR  */
+ DEFINE_INT_CURR("NOK")                /* Norwegian Krone  */
+ DEFINE_INT_CURR("NPR")                /* Nepalese Rupee  */
+ DEFINE_INT_CURR("NZD")                /* New Zealand Dollar  */
+@@ -124,6 +136,7 @@ DEFINE_INT_CURR("PGK")             /* Papau New Gui
+ DEFINE_INT_CURR("PHP")                /* Philippines Peso  */
+ DEFINE_INT_CURR("PKR")                /* Pakistan Rupee  */
+ DEFINE_INT_CURR("PLN")                /* Polish Zloty  */
++DEFINE_INT_CURR("PTE")                /* Portugese Escudo -> EUR  */
+ DEFINE_INT_CURR("PYG")                /* Paraguay Guarani  */
+ DEFINE_INT_CURR("QAR")                /* Qatar Rial  */
+ DEFINE_INT_CURR("ROL")                /* Romanian Leu  */
+--- glibc-2.3.6/locale/programs/3level.h       13 Jun 2003 20:45:38 -0000      1.5
++++ glibc-2.3.6-fedora/locale/programs/3level.h        22 Sep 2004 21:20:58 -0000      1.5.2.1
+@@ -204,6 +204,42 @@ CONCAT(TABLE,_iterate) (struct TABLE *t,
+       }
+     }
+ }
++
++/* GCC ATM seems to do a poor job with pointers to nested functions passed
++   to inlined functions.  Help it a little bit with this hack.  */
++#define wchead_table_iterate(tp, fn) \
++do                                                                          \
++  {                                                                         \
++    struct wchead_table *t = (tp);                                          \
++    uint32_t index1;                                                        \
++    for (index1 = 0; index1 < t->level1_size; index1++)                             \
++      {                                                                             \
++      uint32_t lookup1 = t->level1[index1];                                 \
++      if (lookup1 != ((uint32_t) ~0))                                       \
++        {                                                                   \
++          uint32_t lookup1_shifted = lookup1 << t->q;                       \
++          uint32_t index2;                                                  \
++          for (index2 = 0; index2 < (1 << t->q); index2++)                  \
++            {                                                               \
++              uint32_t lookup2 = t->level2[index2 + lookup1_shifted];       \
++              if (lookup2 != ((uint32_t) ~0))                               \
++                {                                                           \
++                  uint32_t lookup2_shifted = lookup2 << t->p;               \
++                  uint32_t index3;                                          \
++                  for (index3 = 0; index3 < (1 << t->p); index3++)          \
++                    {                                                       \
++                      struct element_t *lookup3                             \
++                        = t->level3[index3 + lookup2_shifted];              \
++                      if (lookup3 != NULL)                                  \
++                        fn ((((index1 << t->q) + index2) << t->p) + index3, \
++                            lookup3);                                       \
++                    }                                                       \
++                }                                                           \
++            }                                                               \
++        }                                                                   \
++      }                                                                             \
++  } while (0)
++
+ #endif
+ #ifndef NO_FINALIZE
+--- glibc-2.3.6/localedata/Makefile    7 Aug 2004 23:38:13 -0000       1.101
++++ glibc-2.3.6-fedora/localedata/Makefile     22 Sep 2004 21:20:58 -0000      1.101.2.1
+@@ -222,6 +222,7 @@ $(INSTALL-SUPPORTED-LOCALES): install-lo
+       echo -n '...'; \
+       input=`echo $$locale | sed 's/\([^.]*\)[^@]*\(.*\)/\1\2/'`; \
+       $(LOCALEDEF) --alias-file=../intl/locale.alias \
++                   --no-archive \
+                    -i locales/$$input -c -f charmaps/$$charset \
+                    $(addprefix --prefix=,$(install_root)) $$locale; \
+       echo ' done'; \
+--- glibc-2.3.6/localedata/SUPPORTED   18 Jul 2005 01:50:35 -0000      1.72.2.2
++++ glibc-2.3.6-fedora/localedata/SUPPORTED    18 Jul 2005 04:40:55 -0000      1.71.2.2.2.1
+@@ -68,6 +68,7 @@ cy_GB.UTF-8/UTF-8 \
+ cy_GB/ISO-8859-14 \
+ da_DK.UTF-8/UTF-8 \
+ da_DK/ISO-8859-1 \
++da_DK.ISO-8859-15/ISO-8859-15 \
+ de_AT.UTF-8/UTF-8 \
+ de_AT/ISO-8859-1 \
+ de_AT@euro/ISO-8859-15 \
+@@ -94,6 +95,7 @@ en_DK.UTF-8/UTF-8 \
+ en_DK/ISO-8859-1 \
+ en_GB.UTF-8/UTF-8 \
+ en_GB/ISO-8859-1 \
++en_GB.ISO-8859-15/ISO-8859-15 \
+ en_HK.UTF-8/UTF-8 \
+ en_HK/ISO-8859-1 \
+ en_IE.UTF-8/UTF-8 \
+@@ -108,6 +110,7 @@ en_SG.UTF-8/UTF-8 \
+ en_SG/ISO-8859-1 \
+ en_US.UTF-8/UTF-8 \
+ en_US/ISO-8859-1 \
++en_US.ISO-8859-15/ISO-8859-15 \
+ en_ZA.UTF-8/UTF-8 \
+ en_ZA/ISO-8859-1 \
+ en_ZW.UTF-8/UTF-8 \
+@@ -253,6 +256,8 @@ nl_NL/ISO-8859-1 \
+ nl_NL@euro/ISO-8859-15 \
+ nn_NO.UTF-8/UTF-8 \
+ nn_NO/ISO-8859-1 \
++no_NO.UTF-8/UTF-8 \
++no_NO/ISO-8859-1 \
+ oc_FR.UTF-8/UTF-8 \
+ oc_FR/ISO-8859-1 \
+ om_ET/UTF-8 \
+@@ -297,6 +302,7 @@ sv_FI/ISO-8859-1 \
+ sv_FI@euro/ISO-8859-15 \
+ sv_SE.UTF-8/UTF-8 \
+ sv_SE/ISO-8859-1 \
++sv_SE.ISO-8859-15/ISO-8859-15 \
+ ta_IN/UTF-8 \
+ te_IN/UTF-8 \
+ tg_TJ.UTF-8/UTF-8 \
+--- glibc-2.3.6/localedata/locales/cy_GB       28 Sep 2004 04:37:33 -0000      1.4
++++ glibc-2.3.6-fedora/localedata/locales/cy_GB        29 Sep 2004 08:48:23 -0000      1.3.2.2
+@@ -248,8 +248,11 @@ mon         "<U0049><U006F><U006E><U0061
+ d_t_fmt     "<U0044><U0079><U0064><U0064><U0020><U0025><U0041><U0020><U0025><U0064><U0020><U006d><U0069><U0073><U0020><U0025><U0042><U0020><U0025><U0059><U0020><U0025><U0054><U0020><U0025><U005A>"
+ d_fmt       "<U0025><U0064><U002E><U0025><U006D><U002E><U0025><U0079>"
+ t_fmt       "<U0025><U0054>"
+-am_pm       "";""
+-t_fmt_ampm  ""
++am_pm       "<U0041><U004D>";"<U0050><U004D>"
++t_fmt_ampm  "<U0025><U006C><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U0050><U0020><U0025><U005A>"
++date_fmt    "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065>/
++<U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020>/
++<U0025><U005A><U0020><U0025><U0059>"
+ END LC_TIME
+ LC_MESSAGES
+--- glibc-2.3.6/localedata/locales/en_GB       31 Oct 2004 23:42:26 -0000      1.12
++++ glibc-2.3.6-fedora/localedata/locales/en_GB        2 Nov 2004 12:25:47 -0000       1.10.2.2
+@@ -112,8 +112,8 @@ mon         "<U004A><U0061><U006E><U0075
+ d_t_fmt     "<U0025><U0061><U0020><U0025><U0064><U0020><U0025><U0062><U0020><U0025><U0059><U0020><U0025><U0054><U0020><U0025><U005A>"
+ d_fmt       "<U0025><U0064><U002F><U0025><U006D><U002F><U0025><U0079>"
+ t_fmt       "<U0025><U0054>"
+-am_pm       "";""
+-t_fmt_ampm  ""
++am_pm       "<U0041><U004D>";"<U0050><U004D>"
++t_fmt_ampm  "<U0025><U006C><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U0050><U0020><U0025><U005A>"
+ date_fmt      "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065>/
+ <U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020>/
+ <U0025><U005A><U0020><U0025><U0059>"
+--- glibc-2.3.6/localedata/locales/en_US       31 Oct 2004 23:42:26 -0000      1.9
++++ glibc-2.3.6-fedora/localedata/locales/en_US        2 Nov 2004 12:25:47 -0000       1.7.2.2
+@@ -100,7 +100,6 @@ mon        "<U004A><U0061><U006E><U0075><U0061>
+       "<U004F><U0063><U0074><U006F><U0062><U0065><U0072>";/
+       "<U004E><U006F><U0076><U0065><U006D><U0062><U0065><U0072>";/
+       "<U0044><U0065><U0063><U0065><U006D><U0062><U0065><U0072>"
+-am_pm   "";""
+ % Appropriate date and time representation (%c)
+ %     "%a %d %b %Y %r %Z"
+ d_t_fmt "<U0025><U0061><U0020><U0025><U0064><U0020><U0025><U0062><U0020><U0025><U0059><U0020><U0025><U0072><U0020><U0025><U005A>"
+--- glibc-2.3.6/localedata/locales/no_NO 1 Jan 1970 00:00:00 -0000
++++ glibc-2.3.6-fedora/localedata/locales/no_NO        22 Sep 2004 21:21:01 -0000      1.11.2.1
+@@ -0,0 +1,69 @@
++escape_char   /
++comment_char    %
++
++% Norwegian language locale for Norway
++% Source: Norsk Standardiseringsforbund
++% Address: University Library,
++%   Drammensveien 41, N-9242 Oslo, Norge
++% Contact: Kolbjoern Aamboe
++% Tel: +47 - 22859109
++% Fax: +47 - 22434497
++% Email: kolbjorn.aambo@usit.uio.no
++% Language: no
++% Territory: NO
++% Revision: 4.3
++% Date: 1996-10-15
++% Application: general
++% Users: general
++% Repertoiremap: mnemonic.ds
++% Charset: ISO-8859-1
++% Distribution and use is free, also
++% for commercial purposes.
++
++LC_IDENTIFICATION
++copy "nb_NO"
++END LC_IDENTIFICATION
++
++LC_COLLATE
++copy "nb_NO"
++END LC_COLLATE
++
++LC_CTYPE
++copy "nb_NO"
++END LC_CTYPE
++
++LC_MONETARY
++copy "nb_NO"
++END LC_MONETARY
++
++LC_NUMERIC
++copy "nb_NO"
++END LC_NUMERIC
++
++LC_TIME
++copy "nb_NO"
++END LC_TIME
++
++LC_MESSAGES
++copy "nb_NO"
++END LC_MESSAGES
++
++LC_PAPER
++copy "nb_NO"
++END LC_PAPER
++
++LC_TELEPHONE
++copy "nb_NO"
++END LC_TELEPHONE
++
++LC_MEASUREMENT
++copy "nb_NO"
++END LC_MEASUREMENT
++
++LC_NAME
++copy "nb_NO"
++END LC_NAME
++
++LC_ADDRESS
++copy "nb_NO"
++END LC_ADDRESS
+--- glibc-2.3.6/localedata/locales/zh_TW       31 Oct 2004 23:42:28 -0000      1.7
++++ glibc-2.3.6-fedora/localedata/locales/zh_TW        2 Nov 2004 12:25:57 -0000       1.5.2.2
+@@ -1,7 +1,7 @@
+ comment_char %
+ escape_char /
+ %
+-% Chinese language locale for Taiwan R.O.C.
++% Chinese language locale for Taiwan
+ % charmap: BIG5-CP950
+ %
+ % Original Author:
+@@ -17,7 +17,7 @@ escape_char /
+ % Reference:  http://wwwold.dkuug.dk/JTC1/SC22/WG20/docs/n690.pdf
+ LC_IDENTIFICATION
+-title      "Chinese locale for Taiwan R.O.C."
++title      "Chinese locale for Taiwan"
+ source     ""
+ address    ""
+ contact    ""
+@@ -25,7 +25,7 @@ email      "bug-glibc-locales@gnu.org"
+ tel        ""
+ fax        ""
+ language   "Chinese"
+-territory  "Taiwan R.O.C."
++territory  "Taiwan"
+ revision   "0.2"
+ date       "2000-08-02"
+ %
+--- glibc-2.3.6/nptl/ChangeLog 24 Oct 2005 20:50:59 -0000      1.756.2.11
++++ glibc-2.3.6-fedora/nptl/ChangeLog  4 Nov 2005 01:07:47 -0000       1.706.2.33.2.7
+@@ -561,6 +561,11 @@
+       Move definition inside libpthread, libc, librt check.  Provide
+       definition for rtld.
++2004-09-02  Jakub Jelinek  <jakub@redhat.com>
++
++      * pthread_cond_destroy.c (__pthread_cond_destroy): If there are
++      waiters, awake all waiters on the associated mutex.
++
+ 2004-09-02  Ulrich Drepper  <drepper@redhat.com>
+       * sysdeps/alpha/jmpbuf-unwind.h: Define __libc_unwind_longjmp.
+@@ -2635,6 +2640,11 @@
+       * Makefile [$(build-shared) = yes] (tests): Depend on $(test-modules).
++2003-07-22  Jakub Jelinek  <jakub@redhat.com>
++
++      * descr.h: Don't include lowlevellock.h, pthreaddef.h and dl-sysdep.h
++      if __need_struct_pthread_size, instead define lll_lock_t.
++
+ 2003-07-25  Jakub Jelinek  <jakub@redhat.com>
+       * tst-cancel17.c (do_test): Check if aio_cancel failed.
+--- glibc-2.3.6/nptl/Makefile  18 Jul 2005 03:20:10 -0000      1.165.2.2
++++ glibc-2.3.6-fedora/nptl/Makefile   18 Jul 2005 04:41:02 -0000      1.157.2.8.2.2
+@@ -500,15 +500,19 @@ $(addprefix $(objpfx), \
+     $(tests) $(xtests) $(test-srcs))): $(objpfx)libpthread.so \
+                                      $(objpfx)libpthread_nonshared.a
+ $(objpfx)tst-unload: $(common-objpfx)dlfcn/libdl.so
+-# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so,
++# $(objpfx)linklibc.so is used instead of $(common-objpfx)libc.so,
+ # since otherwise libpthread.so comes before libc.so when linking.
+ $(addprefix $(objpfx), $(tests-reverse)): \
+-  $(objpfx)../libc.so $(objpfx)libpthread.so \
++  $(objpfx)linklibc.so $(objpfx)libpthread.so \
+   $(objpfx)libpthread_nonshared.a
+ $(objpfx)../libc.so: $(common-objpfx)libc.so ;
+ $(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(objpfx)libpthread.a
+ $(objpfx)tst-atfork2.out: $(objpfx)tst-atfork2mod.so
++
++$(objpfx)linklibc.so: $(common-objpfx)libc.so
++      ln -s ../libc.so $@
++generated += libclink.so
+ else
+ $(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a
+ endif
+--- glibc-2.3.6/nptl/descr.h   12 Nov 2004 01:24:24 -0000      1.25
++++ glibc-2.3.6-fedora/nptl/descr.h    12 Nov 2004 16:56:12 -0000      1.23.2.3
+@@ -27,9 +27,13 @@
+ #include <sys/types.h>
+ #include <hp-timing.h>
+ #include <list.h>
++#ifdef __need_struct_pthread_size
++#define lll_lock_t int
++#else
+ #include <lowlevellock.h>
+ #include <pthreaddef.h>
+ #include <dl-sysdep.h>
++#endif
+ #include "../nptl_db/thread_db.h"
+ #include <tls.h>
+ #ifdef HAVE_FORCED_UNWIND
+--- glibc-2.3.6/nptl/pthread_cond_destroy.c    2 Sep 2004 18:45:37 -0000       1.5
++++ glibc-2.3.6-fedora/nptl/pthread_cond_destroy.c     22 Sep 2004 21:21:01 -0000      1.5.2.1
+@@ -44,15 +44,35 @@ __pthread_cond_destroy (cond)
+      broadcasted, but still are using the pthread_cond_t structure,
+      pthread_cond_destroy needs to wait for them.  */
+   unsigned int nwaiters = cond->__data.__nwaiters;
+-  while (nwaiters >= (1 << COND_CLOCK_BITS))
++
++  if (nwaiters >= (1 << COND_CLOCK_BITS))
+     {
+-      lll_mutex_unlock (cond->__data.__lock);
++      /* Wake everybody on the associated mutex in case there are
++         threads that have been requeued to it.
++         Without this, pthread_cond_destroy could block potentially
++         for a long time or forever, as it would depend on other
++         thread's using the mutex.
++         When all threads waiting on the mutex are woken up, pthread_cond_wait
++         only waits for threads to acquire and release the internal
++         condvar lock.  */
++      if (cond->__data.__mutex != NULL
++        && cond->__data.__mutex != (void *) ~0l)
++      {
++        pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
++        lll_futex_wake (&mut->__data.__lock, INT_MAX);
++      }
++
++      do
++      {
++        lll_mutex_unlock (cond->__data.__lock);
+-      lll_futex_wait (&cond->__data.__nwaiters, nwaiters);
++        lll_futex_wait (&cond->__data.__nwaiters, nwaiters);
+-      lll_mutex_lock (cond->__data.__lock);
++        lll_mutex_lock (cond->__data.__lock);
+-      nwaiters = cond->__data.__nwaiters;
++        nwaiters = cond->__data.__nwaiters;
++      }
++      while (nwaiters >= (1 << COND_CLOCK_BITS));
+     }
+   return 0;
+--- glibc-2.3.6/nptl/sysdeps/unix/sysv/linux/kernel-features.h 1 Jan 1970 00:00:00 -0000
++++ glibc-2.3.6-fedora/nptl/sysdeps/unix/sysv/linux/kernel-features.h  22 Sep 2004 21:21:02 -0000      1.1.2.1
+@@ -0,0 +1,6 @@
++#include_next <kernel-features.h>
++
++/* NPTL can always assume all clone thread flags work.  */
++#ifndef __ASSUME_CLONE_THREAD_FLAGS
++# define __ASSUME_CLONE_THREAD_FLAGS  1
++#endif
+--- glibc-2.3.6/nscd/connections.c     18 Jul 2005 08:01:49 -0000      1.64.2.4
++++ glibc-2.3.6-fedora/nscd/connections.c      18 Jul 2005 08:11:00 -0000      1.55.2.5.2.3
+@@ -21,6 +21,7 @@
+ #include <alloca.h>
+ #include <assert.h>
+ #include <atomic.h>
++#include <dlfcn.h>
+ #include <error.h>
+ #include <errno.h>
+ #include <fcntl.h>
+@@ -42,6 +43,7 @@
+ #include <sys/socket.h>
+ #include <sys/stat.h>
+ #include <sys/un.h>
++#include <gnu/lib-names.h>
+ #include "nscd.h"
+ #include "dbg_log.h"
+@@ -1476,19 +1478,39 @@ start_threads (void)
+   pthread_condattr_t condattr;
+   pthread_condattr_init (&condattr);
+-#if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0 \
+-    && defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
++#if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
+   /* Determine whether the monotonous clock is available.  */
+   struct timespec dummy;
+ # if _POSIX_MONOTONIC_CLOCK == 0
+   if (sysconf (_SC_MONOTONIC_CLOCK) > 0)
+ # endif
+-# if _POSIX_CLOCK_SELECTION == 0
+-    if (sysconf (_SC_CLOCK_SELECTION) > 0)
++    {
++# if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0
++#  if _POSIX_CLOCK_SELECTION == 0
++      if (sysconf (_SC_CLOCK_SELECTION) > 0)
++#  endif
++        if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0
++            && pthread_condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
++          timeout_clock = CLOCK_MONOTONIC;
++# elif _POSIX_THREADS > 0
++      if (sysconf (_SC_CLOCK_SELECTION) > 0)
++        {
++          void *h = __libc_dlopen (LIBPTHREAD_SO);
++          int (*condattr_setclock) (pthread_condattr_t *, __clockid_t) = NULL;
++
++          if (h != NULL)
++            condattr_setclock = __libc_dlsym (h, "pthread_condattr_setclock");
++
++          if (condattr_setclock
++              && clock_getres (CLOCK_MONOTONIC, &dummy) == 0
++              && condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
++            timeout_clock = CLOCK_MONOTONIC;
++
++          if (h != NULL)
++            __libc_dlclose (h);
++        }
+ # endif
+-      if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0
+-        && pthread_condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
+-      timeout_clock = CLOCK_MONOTONIC;
++    }
+ #endif
+   pthread_cond_init (&readylist_cond, &condattr);
+@@ -1553,7 +1575,6 @@ start_threads (void)
+   main_loop_poll ();
+ }
+-
+ /* Look up the uid, gid, and supplementary groups to run nscd as. When
+    this function is called, we are not listening on the nscd socket yet so
+    we can just use the ordinary lookup functions without causing a lockup  */
+@@ -1622,3 +1643,18 @@ finish_drop_privileges (void)
+       exit (1);
+     }
+ }
++
++/* Handle the HUP signal which will force a dump of the cache */
++void
++sighup_handler (int signum)
++{
++    /* Prune the password database */
++    prune_cache (&dbs[pwddb], LONG_MAX);
++    
++    /* Prune the group database */
++    prune_cache (&dbs[grpdb], LONG_MAX);
++
++    /* Prune the host database */
++    prune_cache (&dbs[hstdb], LONG_MAX);
++}
++
+--- glibc-2.3.6/nscd/nscd.c    16 Feb 2005 11:29:42 -0000      1.42.2.2
++++ glibc-2.3.6-fedora/nscd/nscd.c     16 Feb 2005 19:56:58 -0000      1.38.2.4.2.1
+@@ -122,9 +122,16 @@ static struct argp argp =
+   options, parse_opt, NULL, doc,
+ };
++/* The SIGHUP handler is extern to this file */
++extern void sighup_handler(int signum);
++
+ /* True if only statistics are requested.  */
+ static bool get_stats;
++#ifdef atomic_init_nscd
++atomic_init_nscd
++#endif
++
+ int
+ main (int argc, char **argv)
+ {
+@@ -266,6 +273,7 @@ main (int argc, char **argv)
+   signal (SIGINT, termination_handler);
+   signal (SIGQUIT, termination_handler);
+   signal (SIGTERM, termination_handler);
++  signal (SIGHUP, sighup_handler);
+   signal (SIGPIPE, SIG_IGN);
+   /* Cleanup files created by a previous 'bind'.  */
+--- glibc-2.3.6/nscd/nscd.conf 3 Oct 2004 21:09:23 -0000       1.10
++++ glibc-2.3.6-fedora/nscd/nscd.conf  4 Oct 2004 08:56:17 -0000       1.8.2.2
+@@ -31,8 +31,8 @@
+ #     logfile                 /var/log/nscd.log
+ #     threads                 6
+ #     max-threads             128
+-#     server-user             nobody
+-#     stat-user               somebody
++      server-user             nscd
++#     stat-user               nocpulse
+       debug-level             0
+ #     reload-count            5
+       paranoia                no
+--- glibc-2.3.6/nscd/nscd_conf.c       3 Oct 2004 21:10:35 -0000       1.16
++++ glibc-2.3.6-fedora/nscd/nscd_conf.c        4 Oct 2004 08:56:17 -0000       1.14.2.2
+@@ -230,7 +230,10 @@ nscd_parse_file (const char *fname, stru
+               if (strcmp (arg2, "no") == 0)
+                 dbs[cnt].shared = 0;
+               else if (strcmp (arg2, "yes") == 0)
+-                dbs[cnt].shared = 1;
++#ifndef atomic_supports_shared
++#define atomic_supports_shared 1
++#endif
++                dbs[cnt].shared = atomic_supports_shared;
+               break;
+             }
+         if (cnt == lastdb)
+--- glibc-2.3.6/posix/Makefile 17 Oct 2005 09:05:20 -0000      1.179.2.4
++++ glibc-2.3.6-fedora/posix/Makefile  23 Oct 2005 01:27:00 -0000      1.171.2.9.2.4
+@@ -106,7 +106,8 @@ generated := $(addprefix wordexp-test-re
+            bug-regex21-mem bug-regex21.mtrace \
+            tst-rxspencer-mem tst-rxspencer.mtrace tst-getconf.out \
+            tst-pcre-mem tst-pcre.mtrace tst-boost-mem tst-boost.mtrace \
+-           bug-ga2.mtrace bug-ga2-mem bug-glob2.mtrace bug-glob2-mem
++           bug-ga2.mtrace bug-ga2-mem bug-glob2.mtrace bug-glob2-mem \
++           getconf.speclist
+ include ../Rules
+@@ -279,12 +280,16 @@ bug-glob2-ENV = MALLOC_TRACE=$(objpfx)bu
+ $(objpfx)bug-glob2-mem: $(objpfx)bug-glob2.out
+       $(common-objpfx)malloc/mtrace $(objpfx)bug-glob2.mtrace > $@
+-$(inst_libexecdir)/getconf: $(objpfx)getconf FORCE
++$(inst_libexecdir)/getconf: $(objpfx)getconf $(objpfx)getconf.speclist FORCE
+       $(addprefix $(..)./scripts/mkinstalldirs ,\
+                   $(filter-out $(wildcard $@),$@))
+-      for spec in `LC_ALL=C GETCONF_DIR=/dev/null \
+-                   $(run-program-prefix) $< \
+-                   _POSIX_V6_WIDTH_RESTRICTED_ENVS`; do \
+-              $(INSTALL_PROGRAM) $< $@/$$spec.new; \
+-              mv -f $@/$$spec.new $@/$$spec; \
++      for spec in `cat $(objpfx)getconf.speclist`; do \
++        $(INSTALL_PROGRAM) $< $@/$$spec.new; \
++        mv -f $@/$$spec.new $@/$$spec; \
+       done
++
++$(objpfx)getconf.speclist: getconf.speclist.h
++      $(CC) -E $(CFLAGS) $(CPPFLAGS) $< \
++        | sed -n -e '/START_OF_STRINGS/,$${/POSIX_V6_/{s/^[^"]*"//;s/".*$$//;p}}' \
++        > $@.new
++      mv -f $@.new $@
+--- glibc-2.3.6/posix/getconf.speclist.h 1 Jan 1970 00:00:00 -0000
++++ glibc-2.3.6-fedora/posix/getconf.speclist.h        13 Dec 2004 23:32:37 -0000      1.1.2.2
+@@ -0,0 +1,15 @@
++#include <unistd.h>
++const char *START_OF_STRINGS =
++#if _POSIX_V6_ILP32_OFF32 == 1
++"POSIX_V6_ILP32_OFF32"
++#endif
++#if _POSIX_V6_ILP32_OFFBIG == 1
++"POSIX_V6_ILP32_OFFBIG"
++#endif
++#if _POSIX_V6_LP64_OFF64 == 1
++"POSIX_V6_LP64_OFF64"
++#endif
++#if _POSIX_V6_LPBIG_OFFBIG == 1
++"POSIX_V6_LPBIG_OFFBIG"
++#endif
++"";
+--- glibc-2.3.6/sysdeps/generic/dl-cache.h     25 Jun 2003 08:01:22 -0000      1.13
++++ glibc-2.3.6-fedora/sysdeps/generic/dl-cache.h      22 Sep 2004 21:21:07 -0000      1.13.2.1
+@@ -36,6 +36,14 @@
+ # define add_system_dir(dir) add_dir (dir)
+ #endif
++#ifndef arch_startup
++# define arch_startup(argc, argv) do { } while (0)
++#endif
++
++#ifndef add_arch_dirs
++# define add_arch_dirs(config_file) do { } while (0)
++#endif
++
+ #define CACHEMAGIC "ld.so-1.7.0"
+ /* libc5 and glibc 2.0/2.1 use the same format.  For glibc 2.2 another
+--- glibc-2.3.6/sysdeps/i386/bits/atomic.h 1 Jan 1970 00:00:00 -0000
++++ glibc-2.3.6-fedora/sysdeps/i386/bits/atomic.h      5 Oct 2004 12:09:44 -0000       1.1.2.3
+@@ -0,0 +1,410 @@
++/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
++
++   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>
++
++
++typedef int8_t atomic8_t;
++typedef uint8_t uatomic8_t;
++typedef int_fast8_t atomic_fast8_t;
++typedef uint_fast8_t uatomic_fast8_t;
++
++typedef int16_t atomic16_t;
++typedef uint16_t uatomic16_t;
++typedef int_fast16_t atomic_fast16_t;
++typedef uint_fast16_t uatomic_fast16_t;
++
++typedef int32_t atomic32_t;
++typedef uint32_t uatomic32_t;
++typedef int_fast32_t atomic_fast32_t;
++typedef uint_fast32_t uatomic_fast32_t;
++
++typedef int64_t atomic64_t;
++typedef uint64_t uatomic64_t;
++typedef int_fast64_t atomic_fast64_t;
++typedef uint_fast64_t uatomic_fast64_t;
++
++typedef intptr_t atomicptr_t;
++typedef uintptr_t uatomicptr_t;
++typedef intmax_t atomic_max_t;
++typedef uintmax_t uatomic_max_t;
++
++
++#ifndef LOCK_PREFIX
++# ifdef UP
++#  define LOCK_PREFIX /* nothing */
++# else
++#  define LOCK_PREFIX "lock;"
++# endif
++#endif
++
++/* i386 doesn't have cmpxchg* and xadd*.  Instead of being completely
++   non-atomic, atomic_* macros that are using solely i386 instructions
++   are using those atomic instructions and the remaining ones are
++   non-atomic.  When in nscd, use i486+ instructions if on i486+.  */
++
++#ifdef IS_IN_nscd
++
++extern int has_cmpxchg attribute_hidden;
++
++#define atomic_supports_shared has_cmpxchg
++
++#define atomic_init_nscd \
++int has_cmpxchg attribute_hidden;                                           \
++static void __attribute__((constructor))                                    \
++init_has_cmpxchg (void)                                                             \
++{                                                                           \
++  int fl1, fl2;                                                                     \
++  __asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"               \
++         "pushl %0; popfl; pushfl; popl %0; popfl"                          \
++         : "=&r" (fl1), "=&r" (fl2) : "i" (0x00040000));                    \
++  if ((fl1 ^ fl2) & 0x00040000)                                                     \
++    has_cmpxchg = 1;                                                        \
++}
++
++# define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
++  ({ __typeof (*mem) ret;                                                   \
++     if (__builtin_expect (has_cmpxchg, 1))                                 \
++       __asm __volatile (LOCK_PREFIX "cmpxchgb %b2, %1"                             \
++                       : "=a" (ret), "=m" (*mem)                            \
++                       : "q" (newval), "m" (*mem), "0" (oldval));           \
++     else                                                                   \
++       {                                                                    \
++       ret = *mem;                                                          \
++       if (ret == oldval)                                                   \
++         *mem = (newval);                                                   \
++       }                                                                    \
++     ret; })
++
++# define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
++  ({ __typeof (*mem) ret;                                                   \
++     if (__builtin_expect (has_cmpxchg, 1))                                 \
++       __asm __volatile (LOCK_PREFIX "cmpxchgw %w2, %1"                             \
++                       : "=a" (ret), "=m" (*mem)                            \
++                       : "r" (newval), "m" (*mem), "0" (oldval));           \
++     else                                                                   \
++       {                                                                    \
++       ret = *mem;                                                          \
++       if (ret == oldval)                                                   \
++         *mem = (newval);                                                   \
++       }                                                                    \
++     ret; })
++
++# define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
++  ({ __typeof (*mem) ret;                                                   \
++     if (__builtin_expect (has_cmpxchg, 1))                                 \
++       __asm __volatile (LOCK_PREFIX "cmpxchgl %2, %1"                              \
++                       : "=a" (ret), "=m" (*mem)                            \
++                       : "r" (newval), "m" (*mem), "0" (oldval));           \
++     else                                                                   \
++       {                                                                    \
++       ret = *mem;                                                          \
++       if (ret == oldval)                                                   \
++         *mem = (newval);                                                   \
++       }                                                                    \
++     ret; })
++
++/* XXX We do not really need 64-bit compare-and-exchange.  At least
++   not in the moment.  */
++# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
++  ({ __typeof (*mem) ret = *(mem); abort (); ret = (newval); ret = (oldval); })
++
++
++# define atomic_exchange_and_add(mem, value) \
++  ({ __typeof (*mem) __result;                                                      \
++     __typeof (value) __addval = (value);                                   \
++     if (__builtin_expect (! has_cmpxchg, 0))                               \
++       {                                                                    \
++       __typeof (mem) __memp = (mem);                                       \
++       __result = *__memp;                                                  \
++       *__memp += __addval;                                                 \
++       }                                                                    \
++     else if (sizeof (*mem) == 1)                                           \
++       __asm __volatile (LOCK_PREFIX "xaddb %b0, %1"                        \
++                       : "=r" (__result), "=m" (*mem)                       \
++                       : "0" (__addval), "m" (*mem));                       \
++     else if (sizeof (*mem) == 2)                                           \
++       __asm __volatile (LOCK_PREFIX "xaddw %w0, %1"                        \
++                       : "=r" (__result), "=m" (*mem)                       \
++                       : "0" (__addval), "m" (*mem));                       \
++     else if (sizeof (*mem) == 4)                                           \
++       __asm __volatile (LOCK_PREFIX "xaddl %0, %1"                         \
++                       : "=r" (__result), "=m" (*mem)                       \
++                       : "0" (__addval), "m" (*mem));                       \
++     else                                                                   \
++       {                                                                    \
++       __typeof (mem) __memp = (mem);                                       \
++       __typeof (*mem) __tmpval;                                            \
++       __result = *__memp;                                                  \
++       do                                                                   \
++         __tmpval = __result;                                               \
++       while ((__result = __arch_compare_and_exchange_val_64_acq            \
++               (__memp, __result + __addval, __result)) == __tmpval);       \
++       }                                                                    \
++     __result; })
++
++#else
++
++/* We have by default no support for atomic operations.  So define
++   them non-atomic.  If this is a problem somebody will have to come
++   up with real definitions.  */
++
++/* The only basic operation needed is compare and exchange.  */
++#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
++  ({ __typeof (mem) __gmemp = (mem);                                        \
++     __typeof (*mem) __gret = *__gmemp;                                             \
++     __typeof (*mem) __gnewval = (newval);                                  \
++                                                                            \
++     if (__gret == (oldval))                                                \
++       *__gmemp = __gnewval;                                                \
++     __gret; })
++
++#define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
++  ({ __typeof (mem) __gmemp = (mem);                                        \
++     __typeof (*mem) __gnewval = (newval);                                  \
++                                                                            \
++     *__gmemp == (oldval) ? (*__gmemp = __gnewval, 0) : 1; })
++
++/* XXX We do not really need 64-bit compare-and-exchange.  At least
++   not in the moment.  */
++# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
++  ({ __typeof (*mem) ret = *(mem); abort (); ret = (newval); ret = (oldval); })
++
++#endif
++
++/* Note that we need no lock prefix.  */
++#define atomic_exchange_acq(mem, newvalue) \
++  ({ __typeof (*mem) result;                                                \
++     if (sizeof (*mem) == 1)                                                \
++       __asm __volatile ("xchgb %b0, %1"                                    \
++                       : "=r" (result), "=m" (*mem)                         \
++                       : "0" (newvalue), "m" (*mem));                       \
++     else if (sizeof (*mem) == 2)                                           \
++       __asm __volatile ("xchgw %w0, %1"                                    \
++                       : "=r" (result), "=m" (*mem)                         \
++                       : "0" (newvalue), "m" (*mem));                       \
++     else if (sizeof (*mem) == 4)                                           \
++       __asm __volatile ("xchgl %0, %1"                                             \
++                       : "=r" (result), "=m" (*mem)                         \
++                       : "0" (newvalue), "m" (*mem));                       \
++     else                                                                   \
++       {                                                                    \
++       result = 0;                                                          \
++       abort ();                                                            \
++       }                                                                    \
++     result; })
++
++
++#define atomic_add(mem, value) \
++  (void) ({ if (__builtin_constant_p (value) && (value) == 1)               \
++            atomic_increment (mem);                                         \
++          else if (__builtin_constant_p (value) && (value) == -1)           \
++            atomic_decrement (mem);                                         \
++          else if (sizeof (*mem) == 1)                                      \
++            __asm __volatile (LOCK_PREFIX "addb %b1, %0"                    \
++                              : "=m" (*mem)                                 \
++                              : "ir" (value), "m" (*mem));                  \
++          else if (sizeof (*mem) == 2)                                      \
++            __asm __volatile (LOCK_PREFIX "addw %w1, %0"                    \
++                              : "=m" (*mem)                                 \
++                              : "ir" (value), "m" (*mem));                  \
++          else if (sizeof (*mem) == 4)                                      \
++            __asm __volatile (LOCK_PREFIX "addl %1, %0"                     \
++                              : "=m" (*mem)                                 \
++                              : "ir" (value), "m" (*mem));                  \
++          else                                                              \
++            {                                                               \
++              __typeof (value) __addval = (value);                          \
++              __typeof (mem) __memp = (mem);                                \
++              __typeof (*mem) __oldval = *__memp;                           \
++              __typeof (*mem) __tmpval;                                     \
++              do                                                            \
++                __tmpval = __oldval;                                        \
++              while ((__oldval = __arch_compare_and_exchange_val_64_acq     \
++                     (__memp, __oldval + __addval, __oldval)) == __tmpval); \
++            }                                                               \
++          })
++
++
++#define atomic_add_negative(mem, value) \
++  ({ unsigned char __result;                                                \
++     if (sizeof (*mem) == 1)                                                \
++       __asm __volatile (LOCK_PREFIX "addb %b2, %0; sets %1"                \
++                       : "=m" (*mem), "=qm" (__result)                      \
++                       : "iq" (value), "m" (*mem));                         \
++     else if (sizeof (*mem) == 2)                                           \
++       __asm __volatile (LOCK_PREFIX "addw %w2, %0; sets %1"                \
++                       : "=m" (*mem), "=qm" (__result)                      \
++                       : "ir" (value), "m" (*mem));                         \
++     else if (sizeof (*mem) == 4)                                           \
++       __asm __volatile (LOCK_PREFIX "addl %2, %0; sets %1"                 \
++                       : "=m" (*mem), "=qm" (__result)                      \
++                       : "ir" (value), "m" (*mem));                         \
++     else                                                                   \
++       abort ();                                                            \
++     __result; })
++
++
++#define atomic_add_zero(mem, value) \
++  ({ unsigned char __result;                                                \
++     if (sizeof (*mem) == 1)                                                \
++       __asm __volatile (LOCK_PREFIX "addb %b2, %0; setz %1"                \
++                       : "=m" (*mem), "=qm" (__result)                      \
++                       : "ir" (value), "m" (*mem));                         \
++     else if (sizeof (*mem) == 2)                                           \
++       __asm __volatile (LOCK_PREFIX "addw %w2, %0; setz %1"                \
++                       : "=m" (*mem), "=qm" (__result)                      \
++                       : "ir" (value), "m" (*mem));                         \
++     else if (sizeof (*mem) == 4)                                           \
++       __asm __volatile (LOCK_PREFIX "addl %2, %0; setz %1"                 \
++                       : "=m" (*mem), "=qm" (__result)                      \
++                       : "ir" (value), "m" (*mem));                         \
++     else                                                                   \
++       abort ();                                                            \
++     __result; })
++
++
++#define atomic_increment(mem) \
++  (void) ({ if (sizeof (*mem) == 1)                                         \
++            __asm __volatile (LOCK_PREFIX "incb %b0"                        \
++                              : "=m" (*mem)                                 \
++                              : "m" (*mem));                                \
++          else if (sizeof (*mem) == 2)                                      \
++            __asm __volatile (LOCK_PREFIX "incw %w0"                        \
++                              : "=m" (*mem)                                 \
++                              : "m" (*mem));                                \
++          else if (sizeof (*mem) == 4)                                      \
++            __asm __volatile (LOCK_PREFIX "incl %0"                         \
++                              : "=m" (*mem)                                 \
++                              : "m" (*mem));                                \
++          else                                                              \
++            {                                                               \
++              __typeof (mem) __memp = (mem);                                \
++              __typeof (*mem) __oldval = *__memp;                           \
++              __typeof (*mem) __tmpval;                                     \
++              do                                                            \
++                __tmpval = __oldval;                                        \
++              while ((__oldval = __arch_compare_and_exchange_val_64_acq     \
++                     (__memp, __oldval + 1, __oldval)) == __tmpval);        \
++            }                                                               \
++          })
++
++
++#define atomic_increment_and_test(mem) \
++  ({ unsigned char __result;                                                \
++     if (sizeof (*mem) == 1)                                                \
++       __asm __volatile (LOCK_PREFIX "incb %0; sete %b1"                    \
++                       : "=m" (*mem), "=qm" (__result)                      \
++                       : "m" (*mem));                                       \
++     else if (sizeof (*mem) == 2)                                           \
++       __asm __volatile (LOCK_PREFIX "incw %0; sete %w1"                    \
++                       : "=m" (*mem), "=qm" (__result)                      \
++                       : "m" (*mem));                                       \
++     else if (sizeof (*mem) == 4)                                           \
++       __asm __volatile (LOCK_PREFIX "incl %0; sete %1"                             \
++                       : "=m" (*mem), "=qm" (__result)                      \
++                       : "m" (*mem));                                       \
++     else                                                                   \
++       abort ();                                                            \
++     __result; })
++
++
++#define atomic_decrement(mem) \
++  (void) ({ if (sizeof (*mem) == 1)                                         \
++            __asm __volatile (LOCK_PREFIX "decb %b0"                        \
++                              : "=m" (*mem)                                 \
++                              : "m" (*mem));                                \
++          else if (sizeof (*mem) == 2)                                      \
++            __asm __volatile (LOCK_PREFIX "decw %w0"                        \
++                              : "=m" (*mem)                                 \
++                              : "m" (*mem));                                \
++          else if (sizeof (*mem) == 4)                                      \
++            __asm __volatile (LOCK_PREFIX "decl %0"                         \
++                              : "=m" (*mem)                                 \
++                              : "m" (*mem));                                \
++          else                                                              \
++            {                                                               \
++              __typeof (mem) __memp = (mem);                                \
++              __typeof (*mem) __oldval = *__memp;                           \
++              __typeof (*mem) __tmpval;                                     \
++              do                                                            \
++                __tmpval = __oldval;                                        \
++              while ((__oldval = __arch_compare_and_exchange_val_64_acq     \
++                     (__memp, __oldval - 1, __oldval)) == __tmpval);        \
++            }                                                               \
++          })
++
++
++#define atomic_decrement_and_test(mem) \
++  ({ unsigned char __result;                                                \
++     if (sizeof (*mem) == 1)                                                \
++       __asm __volatile (LOCK_PREFIX "decb %b0; sete %1"                    \
++                       : "=m" (*mem), "=qm" (__result)                      \
++                       : "m" (*mem));                                       \
++     else if (sizeof (*mem) == 2)                                           \
++       __asm __volatile (LOCK_PREFIX "decw %w0; sete %1"                    \
++                       : "=m" (*mem), "=qm" (__result)                      \
++                       : "m" (*mem));                                       \
++     else if (sizeof (*mem) == 4)                                           \
++       __asm __volatile (LOCK_PREFIX "decl %0; sete %1"                             \
++                       : "=m" (*mem), "=qm" (__result)                      \
++                       : "m" (*mem));                                       \
++     else                                                                   \
++       abort ();                                                            \
++     __result; })
++
++
++#define atomic_bit_set(mem, bit) \
++  (void) ({ if (sizeof (*mem) == 1)                                         \
++            __asm __volatile (LOCK_PREFIX "orb %b2, %0"                     \
++                              : "=m" (*mem)                                 \
++                              : "m" (*mem), "ir" (1 << (bit)));             \
++          else if (sizeof (*mem) == 2)                                      \
++            __asm __volatile (LOCK_PREFIX "orw %w2, %0"                     \
++                              : "=m" (*mem)                                 \
++                              : "m" (*mem), "ir" (1 << (bit)));             \
++          else if (sizeof (*mem) == 4)                                      \
++            __asm __volatile (LOCK_PREFIX "orl %2, %0"                      \
++                              : "=m" (*mem)                                 \
++                              : "m" (*mem), "ir" (1 << (bit)));             \
++          else                                                              \
++            abort ();                                                       \
++          })
++
++
++#define atomic_bit_test_set(mem, bit) \
++  ({ unsigned char __result;                                                \
++     if (sizeof (*mem) == 1)                                                \
++       __asm __volatile (LOCK_PREFIX "btsb %3, %1; setc %0"                 \
++                       : "=q" (__result), "=m" (*mem)                       \
++                       : "m" (*mem), "ir" (bit));                           \
++     else if (sizeof (*mem) == 2)                                           \
++       __asm __volatile (LOCK_PREFIX "btsw %3, %1; setc %0"                 \
++                       : "=q" (__result), "=m" (*mem)                       \
++                       : "m" (*mem), "ir" (bit));                           \
++     else if (sizeof (*mem) == 4)                                           \
++       __asm __volatile (LOCK_PREFIX "btsl %3, %1; setc %0"                 \
++                       : "=q" (__result), "=m" (*mem)                       \
++                       : "m" (*mem), "ir" (bit));                           \
++     else                                                                   \
++       abort ();                                                            \
++     __result; })
++
++
++#define atomic_delay() asm ("rep; nop")
+--- glibc-2.3.6/sysdeps/ia64/Makefile  16 Aug 2004 06:46:14 -0000      1.10
++++ glibc-2.3.6-fedora/sysdeps/ia64/Makefile   22 Sep 2004 21:21:07 -0000      1.10.2.1
+@@ -12,8 +12,8 @@ elide-routines.os += hp-timing
+ ifeq (yes,$(build-shared))
+ # Compatibility
+-sysdep_routines += ia64libgcc
+-shared-only-routines += ia64libgcc
++sysdep_routines += libgcc-compat
++shared-only-routines += libgcc-compat
+ endif
+ endif
+--- glibc-2.3.6/sysdeps/ia64/ia64libgcc.S      11 May 2002 05:12:35 -0000      1.2
++++ glibc-2.3.6-fedora/sysdeps/ia64/ia64libgcc.S       22 Sep 2004 21:21:07 -0000      1.2.2.1
+@@ -1,350 +0,0 @@
+-/* From the Intel IA-64 Optimization Guide, choose the minimum latency
+-   alternative.  */
+-
+-#include <sysdep.h>
+-#undef ret
+-
+-#include <shlib-compat.h>
+-
+-#if SHLIB_COMPAT(libc, GLIBC_2_2, GLIBC_2_2_6)
+-
+-/* __divtf3
+-   Compute a 80-bit IEEE double-extended quotient.
+-   farg0 holds the dividend.  farg1 holds the divisor.  */
+-
+-ENTRY(___divtf3)
+-      cmp.eq p7, p0 = r0, r0
+-      frcpa.s0 f10, p6 = farg0, farg1
+-      ;;
+-(p6)  cmp.ne p7, p0 = r0, r0
+-      .pred.rel.mutex p6, p7
+-(p6)  fnma.s1 f11 = farg1, f10, f1
+-(p6)  fma.s1 f12 = farg0, f10, f0
+-      ;;
+-(p6)  fma.s1 f13 = f11, f11, f0
+-(p6)  fma.s1 f14 = f11, f11, f11
+-      ;;
+-(p6)  fma.s1 f11 = f13, f13, f11
+-(p6)  fma.s1 f13 = f14, f10, f10
+-      ;;
+-(p6)  fma.s1 f10 = f13, f11, f10
+-(p6)  fnma.s1 f11 = farg1, f12, farg0
+-      ;;
+-(p6)  fma.s1 f11 = f11, f10, f12
+-(p6)  fnma.s1 f12 = farg1, f10, f1
+-      ;;
+-(p6)  fma.s1 f10 = f12, f10, f10
+-(p6)  fnma.s1 f12 = farg1, f11, farg0
+-      ;;
+-(p6)  fma.s0 fret0 = f12, f10, f11
+-(p7)  mov fret0 = f10
+-      br.ret.sptk rp
+-END(___divtf3)
+-      .symver ___divtf3, __divtf3@GLIBC_2.2
+-
+-/* __divdf3
+-   Compute a 64-bit IEEE double quotient.
+-   farg0 holds the dividend.  farg1 holds the divisor.  */
+-
+-ENTRY(___divdf3)
+-      cmp.eq p7, p0 = r0, r0
+-      frcpa.s0 f10, p6 = farg0, farg1
+-      ;;
+-(p6)  cmp.ne p7, p0 = r0, r0
+-      .pred.rel.mutex p6, p7
+-(p6)  fmpy.s1 f11 = farg0, f10
+-(p6)  fnma.s1 f12 = farg1, f10, f1
+-      ;;
+-(p6)  fma.s1 f11 = f12, f11, f11
+-(p6)  fmpy.s1 f13 = f12, f12
+-      ;;
+-(p6)  fma.s1 f10 = f12, f10, f10
+-(p6)  fma.s1 f11 = f13, f11, f11
+-      ;;
+-(p6)  fmpy.s1 f12 = f13, f13
+-(p6)  fma.s1 f10 = f13, f10, f10
+-      ;;
+-(p6)  fma.d.s1 f11 = f12, f11, f11
+-(p6)  fma.s1 f10 = f12, f10, f10
+-      ;;
+-(p6)  fnma.d.s1 f8 = farg1, f11, farg0
+-      ;;
+-(p6)  fma.d fret0 = f8, f10, f11
+-(p7)  mov fret0 = f10
+-      br.ret.sptk rp
+-      ;;
+-END(___divdf3)
+-      .symver ___divdf3, __divdf3@GLIBC_2.2
+-
+-/* __divsf3
+-   Compute a 32-bit IEEE float quotient.
+-   farg0 holds the dividend.  farg1 holds the divisor.  */
+-
+-ENTRY(___divsf3)
+-      cmp.eq p7, p0 = r0, r0
+-      frcpa.s0 f10, p6 = farg0, farg1
+-      ;;
+-(p6)  cmp.ne p7, p0 = r0, r0
+-      .pred.rel.mutex p6, p7
+-(p6)  fmpy.s1 f8 = farg0, f10
+-(p6)  fnma.s1 f9 = farg1, f10, f1
+-      ;;
+-(p6)  fma.s1 f8 = f9, f8, f8
+-(p6)  fmpy.s1 f9 = f9, f9
+-      ;;
+-(p6)  fma.s1 f8 = f9, f8, f8
+-(p6)  fmpy.s1 f9 = f9, f9
+-      ;;
+-(p6)  fma.d.s1 f10 = f9, f8, f8
+-      ;;
+-(p6)  fnorm.s.s0 fret0 = f10
+-(p7)  mov fret0 = f10
+-      br.ret.sptk rp
+-      ;;
+-END(___divsf3)
+-      .symver ___divsf3, __divsf3@GLIBC_2.2
+-
+-/* __divdi3
+-   Compute a 64-bit integer quotient.
+-   in0 holds the dividend.  in1 holds the divisor.  */
+-
+-ENTRY(___divdi3)
+-      .regstk 2,0,0,0
+-      /* Transfer inputs to FP registers.  */
+-      setf.sig f8 = in0
+-      setf.sig f9 = in1
+-      ;;
+-      /* Convert the inputs to FP, so that they won't be treated as
+-         unsigned.  */
+-      fcvt.xf f8 = f8
+-      fcvt.xf f9 = f9
+-      ;;
+-      /* Compute the reciprocal approximation.  */
+-      frcpa.s1 f10, p6 = f8, f9
+-      ;;
+-      /* 3 Newton-Raphson iterations.  */
+-(p6)  fnma.s1 f11 = f9, f10, f1
+-(p6)  fmpy.s1 f12 = f8, f10
+-      ;;
+-(p6)  fmpy.s1 f13 = f11, f11
+-(p6)  fma.s1 f12 = f11, f12, f12
+-      ;;
+-(p6)  fma.s1 f10 = f11, f10, f10
+-(p6)  fma.s1 f11 = f13, f12, f12
+-      ;;
+-(p6)  fma.s1 f10 = f13, f10, f10
+-(p6)  fnma.s1 f12 = f9, f11, f8
+-      ;;
+-(p6)  fma.s1 f10 = f12, f10, f11
+-      ;;
+-      /* Round quotient to an integer.  */
+-      fcvt.fx.trunc.s1 f10 = f10
+-      ;;
+-      /* Transfer result to GP registers.  */
+-      getf.sig ret0 = f10
+-      br.ret.sptk rp
+-      ;;
+-END(___divdi3)
+-      .symver ___divdi3, __divdi3@GLIBC_2.2
+-
+-/* __moddi3
+-   Compute a 64-bit integer modulus.
+-   in0 holds the dividend (a).  in1 holds the divisor (b).  */
+-
+-ENTRY(___moddi3)
+-      .regstk 2,0,0,0
+-      /* Transfer inputs to FP registers.  */
+-      setf.sig f14 = in0
+-      setf.sig f9 = in1
+-      ;;
+-      /* Convert the inputs to FP, so that they won't be treated as
+-         unsigned.  */
+-      fcvt.xf f8 = f14
+-      fcvt.xf f9 = f9
+-      ;;
+-      /* Compute the reciprocal approximation.  */
+-      frcpa.s1 f10, p6 = f8, f9
+-      ;;
+-      /* 3 Newton-Raphson iterations.  */
+-(p6)  fmpy.s1 f12 = f8, f10
+-(p6)  fnma.s1 f11 = f9, f10, f1
+-      ;;
+-(p6)  fma.s1 f12 = f11, f12, f12
+-(p6)  fmpy.s1 f13 = f11, f11
+-      ;;
+-(p6)  fma.s1 f10 = f11, f10, f10
+-(p6)  fma.s1 f11 = f13, f12, f12
+-      ;;
+-      sub in1 = r0, in1
+-(p6)  fma.s1 f10 = f13, f10, f10
+-(p6)  fnma.s1 f12 = f9, f11, f8
+-      ;;
+-      setf.sig f9 = in1
+-(p6)  fma.s1 f10 = f12, f10, f11
+-      ;;
+-      fcvt.fx.trunc.s1 f10 = f10
+-      ;;
+-      /* r = q * (-b) + a  */
+-      xma.l f10 = f10, f9, f14
+-      ;;
+-      /* Transfer result to GP registers.  */
+-      getf.sig ret0 = f10
+-      br.ret.sptk rp
+-      ;;
+-END(___moddi3)
+-      .symver ___moddi3, __moddi3@GLIBC_2.2
+-
+-/* __udivdi3
+-   Compute a 64-bit unsigned integer quotient.
+-   in0 holds the dividend.  in1 holds the divisor.  */
+-
+-ENTRY(___udivdi3)
+-      .regstk 2,0,0,0
+-      /* Transfer inputs to FP registers.  */
+-      setf.sig f8 = in0
+-      setf.sig f9 = in1
+-      ;;
+-      /* Convert the inputs to FP, to avoid FP software-assist faults.  */
+-      fcvt.xuf.s1 f8 = f8
+-      fcvt.xuf.s1 f9 = f9
+-      ;;
+-      /* Compute the reciprocal approximation.  */
+-      frcpa.s1 f10, p6 = f8, f9
+-      ;;
+-      /* 3 Newton-Raphson iterations.  */
+-(p6)  fnma.s1 f11 = f9, f10, f1
+-(p6)  fmpy.s1 f12 = f8, f10
+-      ;;
+-(p6)  fmpy.s1 f13 = f11, f11
+-(p6)  fma.s1 f12 = f11, f12, f12
+-      ;;
+-(p6)  fma.s1 f10 = f11, f10, f10
+-(p6)  fma.s1 f11 = f13, f12, f12
+-      ;;
+-(p6)  fma.s1 f10 = f13, f10, f10
+-(p6)  fnma.s1 f12 = f9, f11, f8
+-      ;;
+-(p6)  fma.s1 f10 = f12, f10, f11
+-      ;;
+-      /* Round quotient to an unsigned integer.  */
+-      fcvt.fxu.trunc.s1 f10 = f10
+-      ;;
+-      /* Transfer result to GP registers.  */
+-      getf.sig ret0 = f10
+-      br.ret.sptk rp
+-      ;;
+-END(___udivdi3)
+-      .symver ___udivdi3, __udivdi3@GLIBC_2.2
+-
+-/* __umoddi3
+-   Compute a 64-bit unsigned integer modulus.
+-   in0 holds the dividend (a).  in1 holds the divisor (b).  */
+-
+-ENTRY(___umoddi3)
+-      .regstk 2,0,0,0
+-      /* Transfer inputs to FP registers.  */
+-      setf.sig f14 = in0
+-      setf.sig f9 = in1
+-      ;;
+-      /* Convert the inputs to FP, to avoid FP software assist faults.  */
+-      fcvt.xuf.s1 f8 = f14
+-      fcvt.xuf.s1 f9 = f9
+-      ;;
+-      /* Compute the reciprocal approximation.  */
+-      frcpa.s1 f10, p6 = f8, f9
+-      ;;
+-      /* 3 Newton-Raphson iterations.  */
+-(p6)  fmpy.s1 f12 = f8, f10
+-(p6)  fnma.s1 f11 = f9, f10, f1
+-      ;;
+-(p6)  fma.s1 f12 = f11, f12, f12
+-(p6)  fmpy.s1 f13 = f11, f11
+-      ;;
+-(p6)  fma.s1 f10 = f11, f10, f10
+-(p6)  fma.s1 f11 = f13, f12, f12
+-      ;;
+-      sub in1 = r0, in1
+-(p6)  fma.s1 f10 = f13, f10, f10
+-(p6)  fnma.s1 f12 = f9, f11, f8
+-      ;;
+-      setf.sig f9 = in1
+-(p6)  fma.s1 f10 = f12, f10, f11
+-      ;;
+-      /* Round quotient to an unsigned integer.  */
+-      fcvt.fxu.trunc.s1 f10 = f10
+-      ;;
+-      /* r = q * (-b) + a  */
+-      xma.l f10 = f10, f9, f14
+-      ;;
+-      /* Transfer result to GP registers.  */
+-      getf.sig ret0 = f10
+-      br.ret.sptk rp
+-      ;;
+-END(___umoddi3)
+-      .symver ___umoddi3, __umoddi3@GLIBC_2.2
+-
+-/* __multi3
+-   Compute a 128-bit multiply of 128-bit multiplicands.
+-   in0/in1 holds one multiplicand (a), in2/in3 holds the other one (b).  */
+-
+-ENTRY(___multi3)
+-      .regstk 4,0,0,0
+-      setf.sig f6 = in1
+-      movl r19 = 0xffffffff
+-      setf.sig f7 = in2
+-      ;;
+-      and r14 = r19, in0
+-      ;;
+-      setf.sig f10 = r14
+-      and r14 = r19, in2
+-      xmpy.l f9 = f6, f7
+-      ;;
+-      setf.sig f6 = r14
+-      shr.u r14 = in0, 32
+-      ;;
+-      setf.sig f7 = r14
+-      shr.u r14 = in2, 32
+-      ;;
+-      setf.sig f8 = r14
+-      xmpy.l f11 = f10, f6
+-      xmpy.l f6 = f7, f6
+-      ;;
+-      getf.sig r16 = f11
+-      xmpy.l f7 = f7, f8
+-      ;;
+-      shr.u r14 = r16, 32
+-      and r16 = r19, r16
+-      getf.sig r17 = f6
+-      setf.sig f6 = in0
+-      ;;
+-      setf.sig f11 = r14
+-      getf.sig r21 = f7
+-      setf.sig f7 = in3
+-      ;;
+-      xma.l f11 = f10, f8, f11
+-      xma.l f6 = f6, f7, f9
+-      ;;
+-      getf.sig r18 = f11
+-      ;;
+-      add r18 = r18, r17
+-      ;;
+-      and r15 = r19, r18
+-      cmp.ltu p7, p6 = r18, r17
+-      ;;
+-      getf.sig r22 = f6
+-(p7)  adds r14 = 1, r19
+-      ;;
+-(p7)  add r21 = r21, r14
+-      shr.u r14 = r18, 32
+-      shl r15 = r15, 32
+-      ;;
+-      add r20 = r21, r14
+-      ;;
+-      add ret0 = r15, r16
+-      add ret1 = r22, r20
+-      br.ret.sptk rp
+-      ;;
+-END(___multi3)
+-      .symver ___multi3, __multi3@GLIBC_2.2
+-
+-#endif
+--- glibc-2.3.6/sysdeps/ia64/libgcc-compat.c 1 Jan 1970 00:00:00 -0000
++++ glibc-2.3.6-fedora/sysdeps/ia64/libgcc-compat.c    22 Sep 2004 21:21:08 -0000      1.1.2.1
+@@ -0,0 +1,84 @@
++/* pre-.hidden libgcc compatibility
++   Copyright (C) 2002 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 <stdint.h>
++#include <shlib-compat.h>
++
++#if SHLIB_COMPAT(libc, GLIBC_2_2, GLIBC_2_2_6)
++
++typedef int int128_t __attribute__((__mode__(TI)));
++
++extern long double __divtf3 (long double, long double) attribute_hidden;
++long double INTUSE (__divtf3) (long double x, long double y)
++{
++  return __divtf3 (x, y);
++}
++symbol_version (INTUSE (__divtf3), __divtf3, GLIBC_2.2);
++
++extern double __divdf3 (double, double) attribute_hidden;
++double INTUSE (__divdf3) (double x, double y)
++{
++  return __divdf3 (x, y);
++}
++symbol_version (INTUSE (__divdf3), __divdf3, GLIBC_2.2);
++
++extern float __divsf3 (float, float) attribute_hidden;
++float INTUSE (__divsf3) (float x, float y)
++{
++  return __divsf3 (x, y);
++}
++symbol_version (INTUSE (__divsf3), __divsf3, GLIBC_2.2);
++
++extern int64_t __divdi3 (int64_t, int64_t) attribute_hidden;
++int64_t INTUSE (__divdi3) (int64_t x, int64_t y)
++{
++  return __divdi3 (x, y);
++}
++symbol_version (INTUSE (__divdi3), __divdi3, GLIBC_2.2);
++
++extern int64_t __moddi3 (int64_t, int64_t) attribute_hidden;
++int64_t INTUSE (__moddi3) (int64_t x, int64_t y)
++{
++  return __moddi3 (x, y);
++}
++symbol_version (INTUSE (__moddi3), __moddi3, GLIBC_2.2);
++
++extern uint64_t __udivdi3 (uint64_t, uint64_t) attribute_hidden;
++uint64_t INTUSE (__udivdi3) (uint64_t x, uint64_t y)
++{
++  return __udivdi3 (x, y);
++}
++symbol_version (INTUSE (__udivdi3), __udivdi3, GLIBC_2.2);
++
++extern uint64_t __umoddi3 (uint64_t, uint64_t) attribute_hidden;
++uint64_t INTUSE (__umoddi3) (uint64_t x, uint64_t y)
++{
++  return __umoddi3 (x, y);
++}
++symbol_version (INTUSE (__umoddi3), __umoddi3, GLIBC_2.2);
++
++extern int128_t __multi3 (int128_t, int128_t) attribute_hidden;
++int128_t INTUSE (__multi3) (int128_t x, int128_t y)
++{
++  return __multi3 (x, y);
++}
++symbol_version (INTUSE (__multi3), __multi3, GLIBC_2.2);
++
++#endif
+--- glibc-2.3.6/sysdeps/unix/nice.c    28 Sep 2002 19:13:13 -0000      1.6
++++ glibc-2.3.6-fedora/sysdeps/unix/nice.c     22 Sep 2004 21:21:08 -0000      1.6.2.1
+@@ -41,7 +41,12 @@ nice (int incr)
+       __set_errno (save);
+     }
+-  result = setpriority (PRIO_PROCESS, 0, prio + incr);
++  prio += incr;
++  if (prio < PRIO_MIN)
++    prio = PRIO_MIN;
++  else if (prio >= PRIO_MAX)
++    prio = PRIO_MAX - 1;
++  result = setpriority (PRIO_PROCESS, 0, prio);
+   if (result != -1)
+     return getpriority (PRIO_PROCESS, 0);
+   else
+--- glibc-2.3.6/sysdeps/unix/sysv/linux/paths.h        15 Nov 2000 23:06:47 -0000      1.11
++++ glibc-2.3.6-fedora/sysdeps/unix/sysv/linux/paths.h 22 Sep 2004 21:21:08 -0000      1.11.4.1
+@@ -61,7 +61,7 @@
+ #define       _PATH_TTY       "/dev/tty"
+ #define       _PATH_UNIX      "/boot/vmlinux"
+ #define _PATH_UTMP    "/var/run/utmp"
+-#define       _PATH_VI        "/usr/bin/vi"
++#define       _PATH_VI        "/bin/vi"
+ #define _PATH_WTMP    "/var/log/wtmp"
+ /* Provide trailing slash, since mostly used for building pathnames. */
+--- glibc-2.3.6/sysdeps/unix/sysv/linux/readonly-area.c        18 Oct 2004 04:17:11 -0000      1.1
++++ glibc-2.3.6-fedora/sysdeps/unix/sysv/linux/readonly-area.c 20 Oct 2004 11:04:51 -0000      1.1.2.2
+@@ -33,7 +33,10 @@ __readonly_area (const char *ptr, size_t
+   FILE *fp = fopen ("/proc/self/maps", "rc");
+   if (fp == NULL)
+-    return -1;
++    /* We don't know.  Returning 1 here means that programs using %n
++       and -D_FORTIFY_SOURCE=2 will work even when /proc is not mounted,
++       but will allow %n even in writable areas.  */
++    return 1;
+   /* We need no locking.  */
+   __fsetlocking (fp, FSETLOCKING_BYCALLER);
+--- glibc-2.3.6/sysdeps/unix/sysv/linux/tcsetattr.c    10 Sep 2003 19:16:07 -0000      1.16
++++ glibc-2.3.6-fedora/sysdeps/unix/sysv/linux/tcsetattr.c     22 Sep 2004 21:21:08 -0000      1.16.2.1
+@@ -49,6 +49,7 @@ tcsetattr (fd, optional_actions, termios
+ {
+   struct __kernel_termios k_termios;
+   unsigned long int cmd;
++  int retval;
+   switch (optional_actions)
+     {
+@@ -80,6 +81,35 @@ tcsetattr (fd, optional_actions, termios
+   memcpy (&k_termios.c_cc[0], &termios_p->c_cc[0],
+         __KERNEL_NCCS * sizeof (cc_t));
+-  return INLINE_SYSCALL (ioctl, 3, fd, cmd, &k_termios);
++  retval = INLINE_SYSCALL (ioctl, 3, fd, cmd, &k_termios);
++
++  if (retval == 0 && cmd == TCSETS)
++    {
++      /* The Linux kernel has a bug which silently ignore the invalid
++        c_cflag on pty. We have to check it here. */
++      int save = errno;
++      retval = INLINE_SYSCALL (ioctl, 3, fd, TCGETS, &k_termios);
++      if (retval)
++       {
++         /* We cannot verify if the setting is ok. We don't return
++            an error (?). */
++         __set_errno (save);
++         retval = 0;
++       }
++      else if ((termios_p->c_cflag & (PARENB | CREAD))
++              != (k_termios.c_cflag & (PARENB | CREAD))
++              || ((termios_p->c_cflag & CSIZE)
++                  && ((termios_p->c_cflag & CSIZE)
++                      != (k_termios.c_cflag & CSIZE))))
++       {
++         /* It looks like the Linux kernel silently changed the
++            PARENB/CREAD/CSIZE bits in c_cflag. Report it as an
++            error. */
++         __set_errno (EINVAL);
++         retval = -1;
++       }
++    }
++
++  return retval;
+ }
+ libc_hidden_def (tcsetattr)
+--- glibc-2.3.6/sysdeps/unix/sysv/linux/i386/dl-cache.h 1 Jan 1970 00:00:00 -0000
++++ glibc-2.3.6-fedora/sysdeps/unix/sysv/linux/i386/dl-cache.h 22 Sep 2004 21:21:08 -0000      1.1.2.1
+@@ -0,0 +1,59 @@
++/* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
++   Copyright (C) 2004 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.  */
++
++static inline int
++is_ia64 (void)
++{
++  unsigned int fl1, fl2;
++
++  /* See if we can use cpuid.  */
++  __asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
++           "pushl %0; popfl; pushfl; popl %0; popfl"
++           : "=&r" (fl1), "=&r" (fl2)
++           : "i" (0x00200000));
++  if (((fl1 ^ fl2) & 0x00200000) == 0)
++    return 0;
++
++  /* Host supports cpuid.  See if cpuid gives capabilities, try
++     CPUID(0).  Preserve %ebx and %ecx; cpuid insn clobbers these, we
++     don't need their CPUID values here, and %ebx may be the PIC
++     register.  */
++  __asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx"
++           : "=a" (fl1) : "0" (0) : "edx", "cc");
++  if (fl1 == 0)
++    return 0;
++
++  /* Invoke CPUID(1), return %edx; caller can examine bits to
++     determine what's supported.  */
++  __asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx"
++           : "=d" (fl2), "=a" (fl1) : "1" (1) : "cc");
++  return (fl2 & (1 << 30)) != 0;
++}
++
++#define arch_startup(argc, argv) \
++  do {                                                                        \
++    /* On IA-64, try to execute 64-bit ldconfig if possible.          \
++       This is because the badly designed /emul/ia32-linux hack               \
++       will cause 32-bit ldconfig to do all sorts of weird things.  */        \
++    if (is_ia64 ())                                                   \
++      execv ("/emul/ia32-linux/../../sbin/ldconfig",                  \
++           (char *const *) argv);                                     \
++  } while (0)
++
++#include_next <dl-cache.h>
+--- glibc-2.3.6/sysdeps/unix/sysv/linux/ia64/dl-cache.h        6 Jul 2001 04:56:17 -0000       1.2
++++ glibc-2.3.6-fedora/sysdeps/unix/sysv/linux/ia64/dl-cache.h 22 Sep 2004 21:21:09 -0000      1.2.4.1
+@@ -22,4 +22,31 @@
+ #define _dl_cache_check_flags(flags) \
+   ((flags) == _DL_CACHE_DEFAULT_ID)
++#define EMUL_HACK "/emul/ia32-linux"
++
++#define arch_startup(argc, argv) unlink (EMUL_HACK LD_SO_CACHE)
++
++#define add_arch_dirs(config_file) \
++  do {                                                        \
++    int save_verbose = opt_verbose;                   \
++    opt_verbose = 0;                                  \
++                                                      \
++    parse_conf (config_file, EMUL_HACK, true);                \
++                                                      \
++    /* Always add the standard search paths.  */      \
++    add_system_dir (EMUL_HACK SLIBDIR);                       \
++    if (strcmp (SLIBDIR, LIBDIR))                     \
++      add_system_dir (EMUL_HACK LIBDIR);              \
++                                                      \
++    char emul_config_file[strlen (config_file)                \
++                        + sizeof EMUL_HACK];          \
++    strcpy (mempcpy (emul_config_file, EMUL_HACK,     \
++                   strlen (EMUL_HACK)), config_file); \
++                                                      \
++    if (! access (emul_config_file, R_OK))            \
++      parse_conf (emul_config_file, EMUL_HACK, true); \
++                                                      \
++    opt_verbose = save_verbose;                               \
++  } while (0)
++
+ #include_next <dl-cache.h>
+--- glibc-2.3.6/sysdeps/unix/sysv/linux/ia64/dl-procinfo.c 1 Jan 1970 00:00:00 -0000
++++ glibc-2.3.6-fedora/sysdeps/unix/sysv/linux/ia64/dl-procinfo.c      22 Sep 2004 21:21:09 -0000      1.1.2.1
+@@ -0,0 +1,5 @@
++#ifdef IS_IN_ldconfig
++#include <sysdeps/i386/dl-procinfo.c>
++#else
++#include <sysdeps/generic/dl-procinfo.c>
++#endif
+--- glibc-2.3.6/sysdeps/unix/sysv/linux/ia64/dl-procinfo.h 1 Jan 1970 00:00:00 -0000
++++ glibc-2.3.6-fedora/sysdeps/unix/sysv/linux/ia64/dl-procinfo.h      22 Sep 2004 21:21:09 -0000      1.1.2.1
+@@ -0,0 +1,5 @@
++#ifdef IS_IN_ldconfig
++#include <sysdeps/unix/sysv/linux/i386/dl-procinfo.h>
++#else
++#include <sysdeps/generic/dl-procinfo.h>
++#endif
+--- glibc-2.3.6/sysdeps/unix/sysv/linux/ia64/ldd-rewrite.sed   17 Jan 2002 06:49:28 -0000      1.2
++++ glibc-2.3.6-fedora/sysdeps/unix/sysv/linux/ia64/ldd-rewrite.sed    22 Sep 2004 21:21:09 -0000      1.2.2.1
+@@ -1 +1 @@
+-s_^\(RTLDLIST=\)\([^  ]*\)-ia64\(\.so\.[0-9.]*\)[     ]*$_\1"\2-ia64\3 \2\3"_
++s_^\(RTLDLIST=\)\([^  ]*\)-ia64\(\.so\.[0-9.]*\)[     ]*$_\1"\2-ia64\3 /emul/ia32-linux\2\3"_
diff --git a/src/patches/glibc/glibc-DT_GNU_HASH.patch b/src/patches/glibc/glibc-DT_GNU_HASH.patch
new file mode 100644 (file)
index 0000000..0983cbc
--- /dev/null
@@ -0,0 +1,34 @@
+--- libc/elf/dl-lookup.c.jj    2005-04-05 22:49:48.000000000 -0400
++++ libc/elf/dl-lookup.c       2008-03-28 12:23:44.000000000 -0400
+@@ -352,8 +352,29 @@ _dl_setup_hash (struct link_map *map)
+   Elf_Symndx *hash;
+   Elf_Symndx nchain;
+-  if (!map->l_info[DT_HASH])
+-    return;
++  if (__builtin_expect (!map->l_info[DT_HASH], 0))
++    {
++#ifdef SHARED
++# define DT_GNU_HASH 0x6ffffef5
++      ElfW(Dyn) *dyn = map->l_ld;
++      if (dyn == NULL)
++      return;
++      while (dyn->d_tag != DT_NULL)
++      if (dyn->d_tag == DT_GNU_HASH)
++        {
++          if (map->l_prev == NULL)
++            GL(dl_ns)[map->l_ns]._ns_loaded = NULL;
++          else
++            map->l_prev->l_next = NULL;
++          --GL(dl_ns)[map->l_ns]._ns_nloaded;
++          _dl_signal_error (0, map->l_name, NULL,
++                            "requires glibc 2.5 or later dynamic linker");
++        }
++      else
++        dyn++;
++      return;
++#endif
++    }
+   hash = (void *) D_PTR (map, l_info[DT_HASH]);
+   map->l_nbuckets = *hash++;
diff --git a/src/patches/glibc/glibc-MALLOC_CHECK_.patch b/src/patches/glibc/glibc-MALLOC_CHECK_.patch
new file mode 100644 (file)
index 0000000..de1457a
--- /dev/null
@@ -0,0 +1,18 @@
+2006-04-24  Jakub Jelinek  <jakub@redhat.com>
+
+       * malloc/arena.c (ptmalloc_init): Don't call __malloc_check_init
+       if MALLOC_CHECK_ env var contains an empty string.
+
+--- libc/malloc/arena.c        6 Mar 2006 06:18:35 -0000       1.20
++++ libc/malloc/arena.c        24 Apr 2006 17:23:50 -0000      1.21
+@@ -551,8 +551,8 @@ ptmalloc_init (void)
+     }
+   s = getenv("MALLOC_CHECK_");
+ #endif
+-  if(s) {
+-    if(s[0]) mALLOPt(M_CHECK_ACTION, (int)(s[0] - '0'));
++  if(s && s[0]) {
++    mALLOPt(M_CHECK_ACTION, (int)(s[0] - '0'));
+     if (check_action != 0)
+       __malloc_check_init();
+   }
diff --git a/src/patches/glibc/glibc-Wundef.patch b/src/patches/glibc/glibc-Wundef.patch
new file mode 100644 (file)
index 0000000..7d3cce4
--- /dev/null
@@ -0,0 +1,38 @@
+2005-10-07  Roland McGrath  <roland@redhat.com>
+
+       [BZ #1438]
+       * include/features.h: Make tests on _FORTIFY_SOURCE and __OPTIMIZE__
+       friendly to -Wundef.
+       (__USE_FORTIFY_LEVEL): Always define it, to 0 if nothing else.
+
+--- libc/include/features.h    17 Feb 2005 01:10:58 -0000      1.38
++++ libc/include/features.h    8 Oct 2005 06:27:44 -0000       1.39
+@@ -262,18 +262,23 @@
+ # define __USE_REENTRANT      1
+ #endif
+-#if _FORTIFY_SOURCE > 0 && __OPTIMIZE__ > 0 \
++#if defined _FORTIFY_SOURCE && defined __OPTIMIZE__ \
++    && _FORTIFY_SOURCE > 0 && __OPTIMIZE__ > 0 \
+     && (__GNUC_PREREQ (4, 1) \
+         || (defined __GNUC_RH_RELEASE__ && __GNUC_PREREQ (4, 0)) \
+         || (defined __GNUC_RH_RELEASE__ && __GNUC_PREREQ (3, 4) \
+             && __GNUC_MINOR__ == 4 \
+             && (__GNUC_PATCHLEVEL__ > 2 \
+-                || (__GNUC_PATCHLEVEL__ == 2 && __GNUC_RH_RELEASE__ >= 8))))
+-# if _FORTIFY_SOURCE == 1
+-#  define __USE_FORTIFY_LEVEL 1
+-# elif _FORTIFY_SOURCE > 1
++                || (__GNUC_PATCHLEVEL__ == 2 \
++                  && defined __GNUC_RH_RELEASE__ \
++                  && __GNUC_RH_RELEASE__ >= 8))))
++# if _FORTIFY_SOURCE > 1
+ #  define __USE_FORTIFY_LEVEL 2
++# else
++#  define __USE_FORTIFY_LEVEL 1
+ # endif
++#else
++# define __USE_FORTIFY_LEVEL 0
+ #endif
+ /* We do support the IEC 559 math functionality, real and complex.  */
diff --git a/src/patches/glibc/glibc-aio-rh171968.patch b/src/patches/glibc/glibc-aio-rh171968.patch
new file mode 100644 (file)
index 0000000..66c2a05
--- /dev/null
@@ -0,0 +1,584 @@
+2006-09-05  Jakub Jelinek  <jakub@redhat.com>
+            Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/pthread/aio_misc.h (AIO_MISC_NOTIFY): Don't decrement
+       counterp if it is already zero.
+
+2006-01-05  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/pthread/aio_misc.h [!DONT_USE_BOOTSTRAP_MAP]
+       (struct waitlist): Don't add cond.
+       * sysdeps/pthread/aio_notify.c [!DONT_USE_BOOTSTRAP_MAP]
+       (__aio_notify): Use AIO_MISC_NOTIFY instead of pthread_cond_signal.
+       * sysdeps/pthread/aio_suspend.c [!DONT_USE_BOOTSTRAP_MAP]: Don't
+       use condvar, use AIO_MISC_WAIT.
+       * sysdeps/pthread/lio_listio.c: Likewise.
+       * rt/Makefile (tests): Add tst-aio9 and tst-aio10.
+       * rt/tst-aio9.c: New file.
+       * rt/tst-aio10.c: New file.
+
+nptl/
+2006-01-07  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/pthread/aio_misc.h (AIO_MISC_WAIT): Work around gcc
+       being too clever and reloading the futex value where it shouldn't.
+
+2006-01-05  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/pthread/aio_misc.h: New file.
+
+--- libc/sysdeps/pthread/aio_misc.h.jj 2003-08-14 02:01:40.000000000 +0200
++++ libc/sysdeps/pthread/aio_misc.h    2006-02-22 19:05:18.000000000 +0100
+@@ -46,7 +46,9 @@ struct waitlist
+   {
+     struct waitlist *next;
++#ifndef DONT_NEED_AIO_MISC_COND
+     pthread_cond_t *cond;
++#endif
+     volatile int *counterp;
+     /* The next field is used in asynchronous `lio_listio' operations.  */
+     struct sigevent *sigevp;
+--- libc/sysdeps/pthread/aio_notify.c.jj       2004-05-26 06:23:43.000000000 +0200
++++ libc/sysdeps/pthread/aio_notify.c  2006-02-22 19:10:15.000000000 +0100
+@@ -144,15 +144,21 @@ __aio_notify (struct requestlist *req)
+     {
+       struct waitlist *next = waitlist->next;
+-      /* Decrement the counter.  This is used in both cases.  */
+-      --*waitlist->counterp;
+-
+       if (waitlist->sigevp == NULL)
+-      pthread_cond_signal (waitlist->cond);
++      {
++#ifdef DONT_NEED_AIO_MISC_COND
++        AIO_MISC_NOTIFY (waitlist);
++#else
++        /* Decrement the counter.  */
++        --*waitlist->counterp;
++
++        pthread_cond_signal (waitlist->cond);
++#endif
++      }
+       else
+       /* This is part of a asynchronous `lio_listio' operation.  If
+          this request is the last one, send the signal.  */
+-      if (*waitlist->counterp == 0)
++      if (--*waitlist->counterp == 0)
+         {
+ #ifdef BROKEN_THREAD_SIGNALS
+           __aio_notify_only (waitlist->sigevp, waitlist->caller_pid);
+--- libc/sysdeps/pthread/aio_suspend.c.jj      2003-08-14 02:04:38.000000000 +0200
++++ libc/sysdeps/pthread/aio_suspend.c 2006-02-22 19:11:54.000000000 +0100
+@@ -44,7 +44,9 @@ struct clparam
+   const struct aiocb *const *list;
+   struct waitlist *waitlist;
+   struct requestlist **requestlist;
++#ifndef DONT_NEED_AIO_MISC_COND
+   pthread_cond_t *cond;
++#endif
+   int nent;
+ };
+@@ -52,6 +54,12 @@ struct clparam
+ static void
+ cleanup (void *arg)
+ {
++#ifdef DONT_NEED_AIO_MISC_COND
++  /* Acquire the mutex.  If pthread_cond_*wait is used this would
++     happen implicitly.  */
++  pthread_mutex_lock (&__aio_requests_mutex);
++#endif
++
+   const struct clparam *param = (const struct clparam *) arg;
+   /* Now remove the entry in the waiting list for all requests
+@@ -75,8 +83,10 @@ cleanup (void *arg)
+         *listp = (*listp)->next;
+       }
++#ifndef DONT_NEED_AIO_MISC_COND
+   /* Release the conditional variable.  */
+   (void) pthread_cond_destroy (param->cond);
++#endif
+   /* Release the mutex.  */
+   pthread_mutex_unlock (&__aio_requests_mutex);
+@@ -89,13 +99,21 @@ aio_suspend (list, nent, timeout)
+      int nent;
+      const struct timespec *timeout;
+ {
++  if (__builtin_expect (nent < 0, 0))
++    {
++      __set_errno (EINVAL);
++      return -1;
++    }
++
+   struct waitlist waitlist[nent];
+   struct requestlist *requestlist[nent];
++#ifndef DONT_NEED_AIO_MISC_COND
+   pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
++#endif
+   int cnt;
+   bool any = false;
+   int result = 0;
+-  int dummy;
++  int cntr = 1;
+   /* Request the mutex.  */
+   pthread_mutex_lock (&__aio_requests_mutex);
+@@ -111,9 +129,11 @@ aio_suspend (list, nent, timeout)
+           if (requestlist[cnt] != NULL)
+             {
++#ifndef DONT_NEED_AIO_MISC_COND
+               waitlist[cnt].cond = &cond;
++#endif
+               waitlist[cnt].next = requestlist[cnt]->waiting;
+-              waitlist[cnt].counterp = &dummy;
++              waitlist[cnt].counterp = &cntr;
+               waitlist[cnt].sigevp = NULL;
+ #ifdef BROKEN_THREAD_SIGNALS
+               waitlist[cnt].caller_pid = 0;   /* Not needed.  */
+@@ -139,12 +159,17 @@ aio_suspend (list, nent, timeout)
+         .list = list,
+         .waitlist = waitlist,
+         .requestlist = requestlist,
++#ifndef DONT_NEED_AIO_MISC_COND
+         .cond = &cond,
++#endif
+         .nent = nent
+       };
+       pthread_cleanup_push (cleanup, &clparam);
++#ifdef DONT_NEED_AIO_MISC_COND
++      AIO_MISC_WAIT (result, cntr, timeout, 1);
++#else
+       if (timeout == NULL)
+       result = pthread_cond_wait (&cond, &__aio_requests_mutex);
+       else
+@@ -166,6 +191,7 @@ aio_suspend (list, nent, timeout)
+         result = pthread_cond_timedwait (&cond, &__aio_requests_mutex,
+                                          &abstime);
+       }
++#endif
+       pthread_cleanup_pop (0);
+     }
+@@ -189,19 +215,23 @@ aio_suspend (list, nent, timeout)
+         *listp = (*listp)->next;
+       }
++#ifndef DONT_NEED_AIO_MISC_COND
+   /* Release the conditional variable.  */
+   if (__builtin_expect (pthread_cond_destroy (&cond) != 0, 0))
+     /* This must never happen.  */
+     abort ();
++#endif
+   if (result != 0)
+     {
+-      /* An error occurred.  Possibly it's EINTR.  We have to translate
++#ifndef DONT_NEED_AIO_MISC_COND
++      /* An error occurred.  Possibly it's ETIMEDOUT.  We have to translate
+        the timeout error report of `pthread_cond_timedwait' to the
+        form expected from `aio_suspend'.  */
+       if (result == ETIMEDOUT)
+       __set_errno (EAGAIN);
+       else
++#endif
+       __set_errno (result);
+       result = -1;
+--- libc/sysdeps/pthread/lio_listio.c.jj       2003-08-14 02:06:07.000000000 +0200
++++ libc/sysdeps/pthread/lio_listio.c  2006-02-22 19:29:04.000000000 +0100
+@@ -113,9 +113,11 @@ lio_listio (mode, list, nent, sig)
+     }
+   else if (mode == LIO_WAIT)
+     {
++#ifndef DONT_NEED_AIO_MISC_COND
+       pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+-      struct waitlist waitlist[nent];
+       int oldstate;
++#endif
++      struct waitlist waitlist[nent];
+       total = 0;
+       for (cnt = 0; cnt < nent; ++cnt)
+@@ -124,7 +126,9 @@ lio_listio (mode, list, nent, sig)
+         if (requests[cnt] != NULL && list[cnt]->aio_lio_opcode != LIO_NOP)
+           {
++#ifndef DONT_NEED_AIO_MISC_COND
+             waitlist[cnt].cond = &cond;
++#endif
+             waitlist[cnt].next = requests[cnt]->waiting;
+             waitlist[cnt].counterp = &total;
+             waitlist[cnt].sigevp = NULL;
+@@ -136,6 +140,9 @@ lio_listio (mode, list, nent, sig)
+           }
+       }
++#ifdef DONT_NEED_AIO_MISC_COND
++      AIO_MISC_WAIT (result, total, NULL, 0);
++#else
+       /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancelation
+        points we must be careful.  We added entries to the waiting lists
+        which we must remove.  So defer cancelation for now.  */
+@@ -151,6 +158,7 @@ lio_listio (mode, list, nent, sig)
+       if (pthread_cond_destroy (&cond) != 0)
+       /* This must never happen.  */
+       abort ();
++#endif
+     }
+   else
+     {
+@@ -179,7 +187,9 @@ lio_listio (mode, list, nent, sig)
+             if (requests[cnt] != NULL
+                 && list[cnt]->aio_lio_opcode != LIO_NOP)
+               {
++#ifndef DONT_NEED_AIO_MISC_COND
+                 waitlist->list[cnt].cond = NULL;
++#endif
+                 waitlist->list[cnt].next = requests[cnt]->waiting;
+                 waitlist->list[cnt].counterp = &waitlist->counter;
+                 waitlist->list[cnt].sigevp = &waitlist->sigev;
+--- libc/rt/Makefile.jj        2005-04-27 10:01:44.000000000 +0200
++++ libc/rt/Makefile   2006-02-22 19:02:58.000000000 +0100
+@@ -43,7 +43,8 @@ librt-routines = $(aio-routines) \
+ tests := tst-shm tst-clock tst-clock_nanosleep tst-timer tst-timer2 \
+        tst-aio tst-aio64 tst-aio2 tst-aio3 tst-aio4 tst-aio5 tst-aio6 \
+-       tst-aio7 tst-mqueue1 tst-mqueue2 tst-mqueue3 tst-mqueue4 \
++       tst-aio7 tst-aio9 tst-aio10 \
++       tst-mqueue1 tst-mqueue2 tst-mqueue3 tst-mqueue4 \
+        tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-mqueue8 tst-mqueue9 \
+        tst-timer3 tst-timer4 tst-timer5 \
+        tst-cpuclock1 tst-cpuclock2 \
+--- libc/rt/tst-aio10.c.jj     2006-02-22 19:02:58.000000000 +0100
++++ libc/rt/tst-aio10.c        2006-02-22 19:02:58.000000000 +0100
+@@ -0,0 +1,119 @@
++#include <aio.h>
++#include <errno.h>
++#include <signal.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <pthread.h>
++#include <unistd.h>
++
++static pthread_barrier_t b;
++static pthread_t main_thread;
++static int flag;
++
++
++static void *
++tf (void *arg)
++{
++  int e = pthread_barrier_wait (&b);
++  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
++    {
++      puts ("child: barrier_wait failed");
++      exit (1);
++    }
++
++  /* There is unfortunately no other way to try to make sure the other
++     thread reached the aio_suspend call.  This test could fail on
++     highly loaded machines.  */
++  sleep (2);
++
++  pthread_kill (main_thread, SIGUSR1);
++
++  while (1)
++    sleep (1000);
++
++  return NULL;
++}
++
++
++static void
++sh (int sig)
++{
++  flag = 1;
++}
++
++
++static int
++do_test (void)
++{
++  main_thread = pthread_self ();
++
++  struct sigaction sa;
++
++  sa.sa_handler = sh;
++  sa.sa_flags = 0;
++  sigemptyset (&sa.sa_mask);
++
++  if (sigaction (SIGUSR1, &sa, NULL) != 0)
++    {
++      puts ("sigaction failed");
++      return 1;
++    }
++
++  if (pthread_barrier_init (&b, NULL, 2) != 0)
++    {
++      puts ("barrier_init");
++      return 1;
++    }
++
++  int fds[2];
++  if (pipe (fds) != 0)
++    {
++      puts ("pipe failed");
++      return 1;
++    }
++
++  char buf[42];
++  struct aiocb req;
++  req.aio_fildes = fds[0];
++  req.aio_lio_opcode = LIO_READ;
++  req.aio_reqprio = 0;
++  req.aio_offset = 0;
++  req.aio_buf = buf;
++  req.aio_nbytes = sizeof (buf);
++  req.aio_sigevent.sigev_notify = SIGEV_NONE;
++
++  pthread_t th;
++  if (pthread_create (&th, NULL, tf, NULL) != 0)
++    {
++      puts ("create failed");
++      return 1;
++    }
++
++  int e = pthread_barrier_wait (&b);
++  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
++    {
++      puts ("parent: barrier_wait failed");
++      exit (1);
++    }
++
++  struct aiocb *list[1];
++  list[0] = &req;
++
++  e = lio_listio (LIO_WAIT, list, 1, NULL);
++  if (e != -1)
++    {
++      puts ("lio_listio succeeded");
++      return 1;
++    }
++  if (errno != EINTR)
++    {
++      printf ("lio_listio did not return EINTR: %d (%d = %m)\n", e, errno);
++      return 1;
++    }
++
++  return 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#define TIMEOUT 5
++#include "../test-skeleton.c"
+--- libc/rt/tst-aio9.c.jj      2006-02-22 19:02:58.000000000 +0100
++++ libc/rt/tst-aio9.c 2006-02-22 19:02:58.000000000 +0100
+@@ -0,0 +1,124 @@
++#include <aio.h>
++#include <errno.h>
++#include <signal.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <pthread.h>
++#include <unistd.h>
++
++static pthread_barrier_t b;
++static pthread_t main_thread;
++static int flag;
++
++
++static void *
++tf (void *arg)
++{
++  int e = pthread_barrier_wait (&b);
++  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
++    {
++      puts ("child: barrier_wait failed");
++      exit (1);
++    }
++
++  /* There is unfortunately no other way to try to make sure the other
++     thread reached the aio_suspend call.  This test could fail on
++     highly loaded machines.  */
++  sleep (2);
++
++  pthread_kill (main_thread, SIGUSR1);
++
++  while (1)
++    sleep (1000);
++
++  return NULL;
++}
++
++
++static void
++sh (int sig)
++{
++  flag = 1;
++}
++
++
++static int
++do_test (void)
++{
++  main_thread = pthread_self ();
++
++  struct sigaction sa;
++
++  sa.sa_handler = sh;
++  sa.sa_flags = 0;
++  sigemptyset (&sa.sa_mask);
++
++  if (sigaction (SIGUSR1, &sa, NULL) != 0)
++    {
++      puts ("sigaction failed");
++      return 1;
++    }
++
++  if (pthread_barrier_init (&b, NULL, 2) != 0)
++    {
++      puts ("barrier_init");
++      return 1;
++    }
++
++  int fds[2];
++  if (pipe (fds) != 0)
++    {
++      puts ("pipe failed");
++      return 1;
++    }
++
++  char buf[42];
++  struct aiocb req;
++  req.aio_fildes = fds[0];
++  req.aio_reqprio = 0;
++  req.aio_offset = 0;
++  req.aio_buf = buf;
++  req.aio_nbytes = sizeof (buf);
++  req.aio_sigevent.sigev_notify = SIGEV_NONE;
++
++  if (aio_read (&req) != 0)
++    {
++      puts ("aio_read failed");
++      return 1;
++    }
++
++  pthread_t th;
++  if (pthread_create (&th, NULL, tf, NULL) != 0)
++    {
++      puts ("create failed");
++      return 1;
++    }
++
++  int e = pthread_barrier_wait (&b);
++  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
++    {
++      puts ("parent: barrier_wait failed");
++      exit (1);
++    }
++
++  const struct aiocb *list[1];
++  list[0] = &req;
++
++  e = aio_suspend (list, 1, NULL);
++  if (e != -1)
++    {
++      puts ("aio_suspend succeeded");
++      return 1;
++    }
++  if (errno != EINTR)
++    {
++      puts ("aio_suspend did not return EINTR");
++      return 1;
++    }
++
++  return 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#define TIMEOUT 5
++#include "../test-skeleton.c"
+--- libc/nptl/sysdeps/pthread/aio_misc.h.jj    2006-02-22 19:02:58.000000000 +0100
++++ libc/nptl/sysdeps/pthread/aio_misc.h       2006-02-22 19:02:58.000000000 +0100
+@@ -0,0 +1,74 @@
++/* Copyright (C) 2006 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.  */
++
++/* We define a special synchronization primitive for AIO.  POSIX
++   conditional variables would be ideal but the pthread_cond_*wait
++   operations do not return on EINTR.  This is a requirement for
++   correct aio_suspend and lio_listio implementations.  */
++
++#include <assert.h>
++#include <pthreadP.h>
++#include <lowlevellock.h>
++
++#define DONT_NEED_AIO_MISC_COND       1
++
++#define AIO_MISC_NOTIFY(waitlist) \
++  do {                                                                              \
++    if (*waitlist->counterp > 0 && --*waitlist->counterp == 0)                      \
++      lll_futex_wake (waitlist->counterp, 1);                               \
++  } while (0)
++
++#define AIO_MISC_WAIT(result, futex, timeout, cancel)                       \
++  do {                                                                              \
++    volatile int *futexaddr = &futex;                                       \
++    int oldval = futex;                                                             \
++                                                                            \
++    if (oldval != 0)                                                        \
++      {                                                                             \
++      pthread_mutex_unlock (&__aio_requests_mutex);                         \
++                                                                            \
++      int oldtype;                                                          \
++      if (cancel)                                                           \
++        oldtype = LIBC_CANCEL_ASYNC ();                                     \
++                                                                            \
++      int status;                                                           \
++      do                                                                    \
++        {                                                                   \
++          status = lll_futex_timed_wait (futexaddr, oldval, timeout);       \
++          if (status != -EWOULDBLOCK)                                       \
++            break;                                                          \
++                                                                            \
++          oldval = *futexaddr;                                              \
++        }                                                                   \
++      while (oldval != 0);                                                  \
++                                                                            \
++      if (cancel)                                                           \
++        LIBC_CANCEL_RESET (oldtype);                                        \
++                                                                            \
++      if (status == -EINTR)                                                 \
++        result = EINTR;                                                     \
++      else if (status == -ETIMEDOUT)                                        \
++        result = EAGAIN;                                                    \
++      else                                                                  \
++        assert (status == 0 || status == -EWOULDBLOCK);                     \
++                                                                            \
++      pthread_mutex_lock (&__aio_requests_mutex);                           \
++      }                                                                             \
++  } while (0)
++
++#include_next <aio_misc.h>
diff --git a/src/patches/glibc/glibc-argp-key.patch b/src/patches/glibc/glibc-argp-key.patch
new file mode 100644 (file)
index 0000000..74580b4
--- /dev/null
@@ -0,0 +1,26 @@
+2006-04-21  Jakub Jelinek  <jakub@redhat.com>
+
+       * argp/argp.h (__option_is_short): Check upper limit of
+       __key.  isprint() requires its argument to have the value
+       of an unsigned char or EOF.
+       Patch by Sergey Poznyakoff <gray@Mirddin.farlep.net>.
+
+--- libc/argp/argp.h   14 Oct 2005 05:53:47 -0000      1.31
++++ libc/argp/argp.h   22 Apr 2006 15:08:26 -0000      1.32
+@@ -24,6 +24,7 @@
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <getopt.h>
++#include <limits.h>
+ #define __need_error_t
+ #include <errno.h>
+@@ -574,7 +575,7 @@ __NTH (__option_is_short (__const struct
+   else
+     {
+       int __key = __opt->key;
+-      return __key > 0 && isprint (__key);
++      return __key > 0 && __key <= UCHAR_MAX && isprint (__key);
+     }
+ }
diff --git a/src/patches/glibc/glibc-argp-vasprintf.patch b/src/patches/glibc/glibc-argp-vasprintf.patch
new file mode 100644 (file)
index 0000000..5bfb378
--- /dev/null
@@ -0,0 +1,39 @@
+2005-08-08  Ulrich Drepper  <drepper@redhat.com>
+       * argp/argp-help.c: Use _IO_vasprintf instead of vasprintf.
+
+2005-08-08  Roland McGrath  <roland@redhat.com>
+
+       * argp/argp-help.c (__argp_error): __asprintf -> vasprintf.
+       (__argp_failure): Likewise.
+
+--- libc/argp/argp-help.c      20 Jul 2005 17:50:29 -0000      1.45
++++ libc/argp/argp-help.c      9 Aug 2005 01:26:22 -0000       1.47
+@@ -48,7 +48,8 @@ char *alloca ();
+ #include <stdarg.h>
+ #include <ctype.h>
+ #include <limits.h>
+-#ifdef USE_IN_LIBIO
++#ifdef _LIBC
++# include <../libio/libioP.h>
+ # include <wchar.h>
+ #endif
+@@ -1768,7 +1769,7 @@ __argp_error (const struct argp_state *s
+           {
+             char *buf;
+-            if (__asprintf (&buf, fmt, ap) < 0)
++            if (_IO_vasprintf (&buf, fmt, ap) < 0)
+               buf = NULL;
+             __fwprintf (stream, L"%s: %s\n",
+@@ -1847,7 +1848,7 @@ __argp_failure (const struct argp_state 
+               {
+                 char *buf;
+-                if (__asprintf (&buf, fmt, ap) < 0)
++                if (_IO_vasprintf (&buf, fmt, ap) < 0)
+                   buf = NULL;
+                 __fwprintf (stream, L": %s", buf);
diff --git a/src/patches/glibc/glibc-argp_usage-NTH.patch b/src/patches/glibc/glibc-argp_usage-NTH.patch
new file mode 100644 (file)
index 0000000..74979cf
--- /dev/null
@@ -0,0 +1,16 @@
+2005-10-13  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1373]
+       * argp/argp.h: Remove __NTH for __argp_usage inline function.
+
+--- libc/argp/argp.h   7 Sep 2004 22:23:45 -0000       1.30
++++ libc/argp/argp.h   14 Oct 2005 05:53:47 -0000      1.31
+@@ -561,7 +561,7 @@ extern void *__argp_input (__const struc
+ # endif
+ ARGP_EI void
+-__NTH (__argp_usage (__const struct argp_state *__state))
++__argp_usage (__const struct argp_state *__state)
+ {
+   __argp_state_help (__state, stderr, ARGP_HELP_STD_USAGE);
+ }
diff --git a/src/patches/glibc/glibc-asctime.patch b/src/patches/glibc/glibc-asctime.patch
new file mode 100644 (file)
index 0000000..958e0a3
--- /dev/null
@@ -0,0 +1,191 @@
+2005-10-14  Ulrich Drepper  <drepper@redhat.com>
+       * time/asctime.c (asctime_internal): Use __snprintf instead of
+       snprintf to avoid PLT entry.
+
+       [BZ #1460]
+       * time/asctime.c (asctime_internal): New function, derived from
+       asctime_r.  Takes additional parameter which is the buffer length.
+       Use snprintf instead sprintf, if it overflows, fail.
+       (asctime_r): Call asctime_internal with 26 as buffer length.
+       (asctime): Call asctime_internal with length of internal buffer.
+       * time/Makefile (tests): Add bug-asctime_r.
+       * time/bug-asctime_r.c: New file.
+
+       [BZ #1459]
+       * time/asctime.c (__asctime_r): Check for tm_year computation to
+       overflow and fail in this case.
+       * time/Makefile (tests): Add bug-asctime.
+       * time/bug-asctime.c: New file.
+
+--- libc/time/asctime.c        3 Aug 2002 12:08:54 -0000       1.15
++++ libc/time/asctime.c        14 Oct 2005 21:15:47 -0000      1.18
+@@ -18,6 +19,7 @@
+ #include "../locale/localeinfo.h"
+ #include <errno.h>
++#include <limits.h>
+ #include <stdio.h>
+ #include <time.h>
+@@ -29,17 +31,9 @@ extern const struct locale_data _nl_C_LC
+ static const char format[] = "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n";
+ static char result[            3+1+ 3+1+20+1+20+1+20+1+20+1+20+1 + 1];
+-/* Returns a string of the form "Day Mon dd hh:mm:ss yyyy\n"
+-   which is the representation of TP in that form.  */
+-char *
+-asctime (const struct tm *tp)
+-{
+-  return __asctime_r (tp, result);
+-}
+-libc_hidden_def (asctime)
+-char *
+-__asctime_r (const struct tm *tp, char *buf)
++static char *
++asctime_internal (const struct tm *tp, char *buf, size_t buflen)
+ {
+   if (tp == NULL)
+     {
+@@ -47,15 +41,51 @@ __asctime_r (const struct tm *tp, char *
+       return NULL;
+     }
+-  if (sprintf (buf, format,
+-             (tp->tm_wday < 0 || tp->tm_wday >= 7 ?
+-              "???" : ab_day_name (tp->tm_wday)),
+-             (tp->tm_mon < 0 || tp->tm_mon >= 12 ?
+-              "???" : ab_month_name (tp->tm_mon)),
+-             tp->tm_mday, tp->tm_hour, tp->tm_min,
+-             tp->tm_sec, 1900 + tp->tm_year) < 0)
++  /* We limit the size of the year which can be printed.  Using the %d
++     format specifier used the addition of 1900 would overflow the
++     number and a negative vaue is printed.  For some architectures we
++     could in theory use %ld or an evern larger integer format but
++     this would mean the output needs more space.  This would not be a
++     problem if the 'asctime_r' interface would be defined sanely and
++     a buffer size would be passed.  */
++  if (__builtin_expect (tp->tm_year > INT_MAX - 1900, 0))
++    {
++    eoverflow:
++      __set_errno (EOVERFLOW);
++      return NULL;
++    }
++
++  int n = __snprintf (buf, buflen, format,
++                    (tp->tm_wday < 0 || tp->tm_wday >= 7 ?
++                     "???" : ab_day_name (tp->tm_wday)),
++                    (tp->tm_mon < 0 || tp->tm_mon >= 12 ?
++                     "???" : ab_month_name (tp->tm_mon)),
++                    tp->tm_mday, tp->tm_hour, tp->tm_min,
++                    tp->tm_sec, 1900 + tp->tm_year);
++  if (n < 0)
+     return NULL;
++  if (n >= buflen)
++    goto eoverflow;
+   return buf;
+ }
++
++
++/* Like asctime, but write result to the user supplied buffer.  The
++   buffer is only guaranteed to be 26 bytes in length.  */
++char *
++__asctime_r (const struct tm *tp, char *buf)
++{
++  return asctime_internal (tp, buf, 26);
++}
+ weak_alias (__asctime_r, asctime_r)
++
++
++/* Returns a string of the form "Day Mon dd hh:mm:ss yyyy\n"
++   which is the representation of TP in that form.  */
++char *
++asctime (const struct tm *tp)
++{
++  return asctime_internal (tp, result, sizeof (result));
++}
++libc_hidden_def (asctime)
+--- libc/time/bug-asctime_r.c 1 Jan 1970 00:00:00 -0000
++++ libc/time/bug-asctime_r.c  14 Oct 2005 15:19:22 -0000      1.2
+@@ -0,0 +1,32 @@
++#include <errno.h>
++#include <limits.h>
++#include <stdio.h>
++#include <time.h>
++
++
++static int
++do_test (void)
++{
++  int result = 0;
++  time_t t = time (NULL);
++  struct tm *tp = localtime (&t);
++  tp->tm_year = 10000 - 1900;
++  char buf[1000];
++  errno = 0;
++  buf[26] = '\xff';
++  char *s = asctime_r (tp, buf);
++  if (s != NULL || errno != EOVERFLOW)
++    {
++      puts ("asctime_r did not fail correctly");
++      result = 1;
++    }
++  if (buf[26] != '\xff')
++    {
++      puts ("asctime_r overwrote 27th byte in buffer");
++      result = 1;
++    }
++  return result;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/time/bug-asctime.c 1 Jan 1970 00:00:00 -0000
++++ libc/time/bug-asctime.c    14 Oct 2005 14:54:27 -0000      1.2
+@@ -0,0 +1,33 @@
++#include <errno.h>
++#include <limits.h>
++#include <stdio.h>
++#include <time.h>
++
++
++static int
++do_test (void)
++{
++  int result = 0;
++  time_t t = time (NULL);
++  struct tm *tp = localtime (&t);
++  tp->tm_year = INT_MAX;
++  errno = 0;
++  char *s = asctime (tp);
++  if (s != NULL || errno != EOVERFLOW)
++    {
++      puts ("asctime did not fail correctly");
++      result = 1;
++    }
++  char buf[1000];
++  errno = 0;
++  s = asctime_r (tp, buf);
++  if (s != NULL || errno != EOVERFLOW)
++    {
++      puts ("asctime_r did not fail correctly");
++      result = 1;
++    }
++  return result;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/time/Makefile 27 Apr 2005 04:31:51 -0000      1.107
++++ libc/time/Makefile 14 Oct 2005 15:16:17 -0000      1.109
+@@ -35,7 +35,7 @@ distribute := datemsk
+ tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
+          tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \
+-         tst-mktime3 tst-strptime2
++         tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r
+ include ../Rules
diff --git a/src/patches/glibc/glibc-bindresvport.patch b/src/patches/glibc/glibc-bindresvport.patch
new file mode 100644 (file)
index 0000000..f735f64
--- /dev/null
@@ -0,0 +1,37 @@
+2005-11-21  Jakub Jelinek  <jakub@redhat.com>
+
+       * sunrpc/bindrsvprt.c (bindresvport): Wrap around to startport
+       in the loop if port is bigger than endport, initially set to
+       ENDPORT.  When changing startport, set endport and port
+       appropriately.
+
+--- libc/sunrpc/bindrsvprt.c   23 May 2005 19:03:43 -0000      1.11
++++ libc/sunrpc/bindrsvprt.c   22 Nov 2005 04:39:05 -0000      1.12
+@@ -74,14 +74,13 @@ bindresvport (int sd, struct sockaddr_in
+   int res = -1;
+   int nports = ENDPORT - startport + 1;
++  int endport = ENDPORT;
+  again:
+   for (i = 0; i < nports; ++i)
+     {
+       sin->sin_port = htons (port++);
+-      if (port > ENDPORT)
+-      {
+-        port = startport;
+-      }
++      if (port > endport)
++      port = startport;
+       res = __bind (sd, sin, sizeof (struct sockaddr_in));
+       if (res >= 0 || errno != EADDRINUSE)
+       break;
+@@ -90,7 +89,9 @@ bindresvport (int sd, struct sockaddr_in
+   if (i == nports && startport != LOWPORT)
+     {
+       startport = LOWPORT;
++      endport = STARTPORT - 1;
+       nports = STARTPORT - LOWPORT;
++      port = LOWPORT + port % (STARTPORT - LOWPORT);
+       goto again;
+     }
diff --git a/src/patches/glibc/glibc-byteswap.patch b/src/patches/glibc/glibc-byteswap.patch
new file mode 100644 (file)
index 0000000..9cbc287
--- /dev/null
@@ -0,0 +1,44 @@
+2007-02-12  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/i386/bits/byteswap.h (__bswap_32): Add __amdfam10__
+       to the list of i486+ CPUs.
+       * sysdeps/x86_64/bits/byteswap.h (__bswap_32): 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.
+
+2006-08-24  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2734]
+       * sysdeps/i386/bits/byteswap.h (__bswap_32): Use same conditions
+       as in the x86-64 code to use bswap.
+
+--- libc/sysdeps/i386/bits/byteswap.h  24 Aug 2006 07:02:16 -0000      1.14
++++ libc/sysdeps/i386/bits/byteswap.h  12 Feb 2007 21:21:03 -0000      1.16
+@@ -65,7 +65,9 @@ __bswap_16 (unsigned short int __bsx)
+ /* To swap the bytes in a word the i486 processors and up provide the
+    `bswap' opcode.  On i386 we have to use three instructions.  */
+ #  if !defined __i486__ && !defined __pentium__ && !defined __pentiumpro__ \
+-      && !defined __pentium4__
++      && !defined __pentium4__ && !defined __k8__ && !defined __athlon__ \
++      && !defined __k6__ && !defined __nocona__ && !defined __core2__ \
++      && !defined __geode__ && !defined __amdfam10__
+ #   define __bswap_32(x)                                                    \
+      (__extension__                                                         \
+       ({ register unsigned int __v, __x = (x);                                      \
+--- libc/sysdeps/x86_64/bits/byteswap.h        17 Aug 2003 06:32:00 -0000      1.1
++++ libc/sysdeps/x86_64/bits/byteswap.h        12 Feb 2007 21:21:03 -0000      1.3
+@@ -59,7 +60,9 @@
+ # 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__           \
++                        || defined __amdfam10__)
+ /* 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/src/patches/glibc/glibc-bz1051.patch b/src/patches/glibc/glibc-bz1051.patch
new file mode 100644 (file)
index 0000000..b4f65fc
--- /dev/null
@@ -0,0 +1,155 @@
+2005-09-22  Roland McGrath  <roland@redhat.com>
+
+       * Makefile ($(objpfx)c++-types-check.out): Use $<, not $^, in command.
+       Reported by Alexandre Oliva <aoliva@redhat.com>.
+
+2005-09-17  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1051]
+       * wctype/wctype.h: Remove stray __END_NAMESPACE_C99.
+       * stdlib/stdlib.h: Use __END_NAMESPACE_STD instead of
+       __END_NAMESPACE_C99 in one place.
+       * scripts/begin-end-check.pl: New file.
+       Patch by Ralph Loader <suckfish@ihug.co.nz>.
+       * Makefile: Add rules to run scripts/begin-end-check.pl.
+
+--- libc/wctype/wctype.h       1 Sep 2002 12:38:06 -0000       1.36
++++ libc/wctype/wctype.h       17 Sep 2005 15:45:42 -0000      1.37
+@@ -44,7 +44,6 @@ typedef unsigned int wint_t;
+ #  ifdef __USE_ISOC99
+ __USING_NAMESPACE_C99(wint_t)
+ #  endif
+-__END_NAMESPACE_C99
+ # endif
+ /* Constant expression of type `wint_t' whose value does not correspond
+--- libc/stdlib/stdlib.h       15 Jul 2005 10:47:20 -0000      1.112
++++ libc/stdlib/stdlib.h       17 Sep 2005 15:42:47 -0000      1.113
+@@ -187,7 +187,7 @@ extern long int strtol (__const char *__
+ extern unsigned long int strtoul (__const char *__restrict __nptr,
+                                 char **__restrict __endptr, int __base)
+      __THROW __nonnull ((1));
+-__END_NAMESPACE_C99
++__END_NAMESPACE_STD
+ #if defined __GLIBC_HAVE_LONG_LONG && defined __USE_BSD
+ /* Convert a string to a quadword integer.  */
+--- libc/Makefile      6 Apr 2005 02:16:07 -0000       1.246
++++ libc/Makefile      17 Sep 2005 17:15:50 -0000      1.248
+@@ -241,7 +241,7 @@ check-data := $(firstword $(wildcard \
+               $(foreach M,$(config-machine) $(base-machine),\
+                         scripts/data/c++-types-$M-$(config-os).data)))
+ ifneq (,$(check-data))
+-$(objpfx)c++-types-check.out: $(check-data)
+-      scripts/check-c++-types.sh $^ $(CXX) $(filter-out -std=gnu99 -Wstrict-prototypes,$(CFLAGS)) $(CPPFLAGS) > $@
++$(objpfx)c++-types-check.out: $(check-data) scripts/check-c++-types.sh
++      scripts/check-c++-types.sh $< $(CXX) $(filter-out -std=gnu99 -Wstrict-prototypes,$(CFLAGS)) $(CPPFLAGS) > $@
+ else
+ $(objpfx)c++-types-check.out:
+@@ -250,6 +250,56 @@ $(objpfx)c++-types-check.out:
+ endif
+ endif
++ifneq ($(PERL),no)
++installed-headers = argp/argp.h assert/assert.h catgets/nl_types.h \
++                  crypt/crypt.h ctype/ctype.h debug/execinfo.h \
++                  dirent/dirent.h dlfcn/dlfcn.h elf/elf.h elf/link.h \
++                  gmon/sys/gmon.h gmon/sys/gmon_out.h gmon/sys/profil.h \
++                  grp/grp.h iconv/iconv.h iconv/gconv.h \
++                  $(wildcard inet/netinet/*.h) \
++                  $(wildcard inet/arpa/*.h inet/protocols/*.h) \
++                  inet/aliases.h inet/ifaddrs.h inet/netinet/ip6.h \
++                  inet/netinet/icmp6.h intl/libintl.h io/sys/stat.h \
++                  io/sys/statfs.h io/sys/vfs.h io/sys/statvfs.h \
++                  io/fcntl.h io/sys/fcntl.h io/poll.h io/sys/poll.h \
++                  io/utime.h io/ftw.h io/fts.h io/sys/sendfile.h \
++                  libio/stdio.h libio/libio.h locale/locale.h \
++                  locale/langinfo.h locale/xlocale.h login/utmp.h \
++                  login/lastlog.h login/pty.h malloc/malloc.h \
++                  malloc/obstack.h malloc/mcheck.h math/math.h \
++                  math/complex.h math/fenv.h math/tgmath.h misc/sys/uio.h \
++                  $(wildcard nis/rpcsvc/*.h) nptl_db/thread_db.h \
++                  nptl/sysdeps/pthread/pthread.h nptl/semaphore.h \
++                  nss/nss.h posix/sys/utsname.h posix/sys/times.h \
++                  posix/sys/wait.h posix/sys/types.h posix/unistd.h \
++                  posix/glob.h posix/regex.h posix/wordexp.h posix/fnmatch.h\
++                  posix/getopt.h posix/tar.h posix/sys/unistd.h \
++                  posix/sched.h posix/re_comp.h posix/wait.h \
++                  posix/cpio.h posix/spawn.h pwd/pwd.h resolv/resolv.h \
++                  resolv/netdb.h $(wildcard resolv/arpa/*.h) \
++                  resource/sys/resource.h resource/sys/vlimit.h \
++                  resource/sys/vtimes.h resource/ulimit.h rt/aio.h \
++                  rt/mqueue.h setjmp/setjmp.h shadow/shadow.h \
++                  signal/signal.h signal/sys/signal.h socket/sys/socket.h \
++                  socket/sys/un.h stdio-common/printf.h \
++                  stdio-common/stdio_ext.h stdlib/stdlib.h stdlib/alloca.h \
++                  stdlib/monetary.h stdlib/fmtmsg.h stdlib/ucontext.h \
++                  sysdeps/generic/inttypes.h sysdeps/generic/stdint.h \
++                  stdlib/errno.h stdlib/sys/errno.h string/string.h \
++                  string/strings.h string/memory.h string/endian.h \
++                  string/argz.h string/envz.h string/byteswap.h \
++                  $(wildcard sunrpc/rpc/*.h sunrpc/rpcsvc/*.h) \
++                  sysvipc/sys/ipc.h sysvipc/sys/msg.h sysvipc/sys/sem.h \
++                  sysvipc/sys/shm.h termios/termios.h \
++                  termios/sys/termios.h termios/sys/ttychars.h time/time.h \
++                  time/sys/time.h time/sys/timeb.h wcsmbs/wchar.h \
++                  wctype/wctype.h
++
++tests: $(objpfx)begin-end-check.out
++$(objpfx)begin-end-check.out: scripts/begin-end-check.pl
++      $(PERL) scripts/begin-end-check.pl $(installed-headers) > $@
++endif
++
+ # The realclean target is just like distclean for the parent, but we want
+ # the subdirs to know the difference in case they care.
+ realclean distclean: parent-clean
+--- libc/scripts/begin-end-check.pl 1 Jan 1970 00:00:00 -0000
++++ libc/scripts/begin-end-check.pl    17 Sep 2005 17:15:23 -0000      1.1
+@@ -0,0 +1,47 @@
++#!/usr/bin/perl
++
++use strict;
++use warnings;
++
++# Check __BEGIN_NAMESPACE ... __END_NAMESPACE pairing in an include file.
++
++my $code = 0;
++for my $path (@ARGV) {
++    my $localcode = 0;
++    my @stack;
++
++    open my $in, '<', $path
++        or die "open $path failed: $!";
++
++    while (<$in>) {
++        if ( /^\s*__BEGIN_(.*)\b/ ) {
++            push @stack, $1;
++        }
++        elsif ( /^\s*__END_(.*)\b/ ) {
++            if (@stack) {
++                my $tag = pop @stack;
++              if ($1 ne $tag) {
++                    print "$path:$.: BEGIN $tag paired with END $1\n";
++                  $localcode = 1;
++              }
++            }
++            else {
++                print "$path:$.: END $1 does not match a begin\n";
++              $localcode = 1;
++            }
++        }
++    }
++
++    if (@stack) {
++      print "$path: Unmatched begin tags " . join (' ', @stack) ."\n";
++      $localcode = 1;
++    }
++
++    if ($localcode == 0) {
++      print "$path: OK\n";
++    } else {
++      $code = $localcode;
++    }
++}
++
++exit $code;
diff --git a/src/patches/glibc/glibc-bz1078.patch b/src/patches/glibc/glibc-bz1078.patch
new file mode 100644 (file)
index 0000000..b4d7e16
--- /dev/null
@@ -0,0 +1,151 @@
+2005-09-27  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1078]
+       * libio/fileops.c (_IO_new_file_xsputn): Determine amount of
+       available space in non-line-buffered buffer correctly.
+       * libio/oldfileops.c (_IO_old_file_xsputn): Likewise.
+       * stdio-common/Makefile (tests): Add tst-fwrite.
+       * stdio-common/tst-fwrite.c: New file.
+
+--- libc/libio/fileops.c       4 Sep 2005 20:07:40 -0000       1.108
++++ libc/libio/fileops.c       27 Sep 2005 18:49:43 -0000      1.109
+@@ -1281,7 +1281,7 @@ _IO_new_file_xsputn (f, data, n)
+   register const char *s = (const char *) data;
+   _IO_size_t to_do = n;
+   int must_flush = 0;
+-  _IO_size_t count;
++  _IO_size_t count = 0;
+   if (n <= 0)
+     return 0;
+@@ -1290,7 +1290,6 @@ _IO_new_file_xsputn (f, data, n)
+      (or the filebuf is unbuffered), use sys_write directly. */
+   /* First figure out how much space is available in the buffer. */
+-  count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
+   if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
+     {
+       count = f->_IO_buf_end - f->_IO_write_ptr;
+@@ -1308,6 +1307,9 @@ _IO_new_file_xsputn (f, data, n)
+           }
+       }
+     }
++  else if (f->_IO_write_end > f->_IO_write_ptr)
++    count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
++
+   /* Then fill the buffer. */
+   if (count > 0)
+     {
+--- libc/libio/oldfileops.c    4 Sep 2005 20:09:33 -0000       1.29
++++ libc/libio/oldfileops.c    27 Sep 2005 18:48:29 -0000      1.30
+@@ -695,7 +695,7 @@ _IO_old_file_xsputn (f, data, n)
+   register const char *s = (char *) data;
+   _IO_size_t to_do = n;
+   int must_flush = 0;
+-  _IO_size_t count;
++  _IO_size_t count = 0;
+   if (n <= 0)
+     return 0;
+@@ -704,7 +704,6 @@ _IO_old_file_xsputn (f, data, n)
+      (or the filebuf is unbuffered), use sys_write directly. */
+   /* First figure out how much space is available in the buffer. */
+-  count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
+   if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
+     {
+       count = f->_IO_buf_end - f->_IO_write_ptr;
+@@ -722,6 +721,9 @@ _IO_old_file_xsputn (f, data, n)
+           }
+       }
+     }
++  else if (f->_IO_write_end > f->_IO_write_ptr)
++    count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
++
+   /* Then fill the buffer. */
+   if (count > 0)
+     {
+--- libc/stdio-common/Makefile 26 Sep 2005 23:58:58 -0000      1.94
++++ libc/stdio-common/Makefile 27 Sep 2005 19:38:26 -0000      1.95
+@@ -53,7 +53,7 @@ tests := tstscanf test_rdwr test-popen t
+        scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf \
+        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-fgets
++       tst-popen tst-unlockedio tst-fmemopen2 tst-fgets tst-fwrite
+ test-srcs = tst-unbputc tst-printf
+--- libc/stdio-common/tst-fwrite.c 1 Jan 1970 00:00:00 -0000
++++ libc/stdio-common/tst-fwrite.c     27 Sep 2005 19:39:08 -0000      1.1
+@@ -0,0 +1,70 @@
++/* Derived from the test case in
++   http://sourceware.org/bugzilla/show_bug.cgi?id=1078.  */
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++
++#define OUT_SIZE 10000
++
++
++static int fd;
++
++static void prepare (void);
++#define PREPARE(argc, argv) prepare ()
++
++static int do_test (void);
++#define TEST_FUNCTION do_test ()
++
++#include "../test-skeleton.c"
++
++
++static void
++prepare (void)
++{
++  fd = create_temp_file ("tst-fwrite.", NULL);
++  if (fd == -1)
++    {
++      puts ("cannot create temporary file");
++      exit (1);
++    }
++}
++
++
++static int
++do_test (void)
++{
++  FILE* f = fdopen (fd, "w+");
++  if (f == NULL) {
++    puts ("cannot create stream");
++    return 1;
++  }
++  puts ("Opened temp file");
++
++  if (fwrite ("a", 1, 1, f) != 1)
++    {
++      puts ("1st fwrite failed");
++      return 1;
++    }
++  puts ("Wrote a byte");
++  fflush (f);
++
++  char buffer[10000];
++  size_t i = fread (buffer, 1, sizeof (buffer), f);
++  printf ("Read %zu bytes\n", i);
++
++  for (i = 0; i < OUT_SIZE; i++)
++    {
++      if (fwrite ("n", 1, 1, f) != 1)
++      {
++        printf ("fwrite in loop round %zu failed\n", i);
++        return 1;
++      }
++
++      if ((i + 1) % 1000 == 0)
++      printf ("wrote %zu bytes ...\n", i + 1);
++    }
++
++  printf ("Wrote %i bytes [done]\n", OUT_SIZE);
++
++  return 0;
++}
diff --git a/src/patches/glibc/glibc-bz1201.patch b/src/patches/glibc/glibc-bz1201.patch
new file mode 100644 (file)
index 0000000..1cc6cc1
--- /dev/null
@@ -0,0 +1,17 @@
+2006-05-02  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1201]
+       * posix/regex.h: g++ still cannot handled [restrict].
+
+--- libc/posix/regex.h 21 Apr 2006 18:20:51 -0000      1.39
++++ libc/posix/regex.h 2 May 2006 21:37:34 -0000       1.40
+@@ -525,7 +525,8 @@ extern int re_exec (const char *);
+ #endif
+ /* gcc 3.1 and up support the [restrict] syntax.  */
+ #ifndef __restrict_arr
+-# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
++# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) \
++     && !defined __GNUG__
+ #  define __restrict_arr __restrict
+ # else
+ #  define __restrict_arr
diff --git a/src/patches/glibc/glibc-bz1228.patch b/src/patches/glibc/glibc-bz1228.patch
new file mode 100644 (file)
index 0000000..ff40aae
--- /dev/null
@@ -0,0 +1,40 @@
+2005-09-13  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #1228]
+       * include/limits.h (LLONG_MIN, LLONG_MAX, ULLONG_MAX): Make sure these
+       are defined for -D_GNU_SOURCE or -D_ISOC99_SOURCE even when not
+       -std=c99.
+
+--- libc/include/limits.h      6 Jul 2001 04:54:52 -0000       1.11
++++ libc/include/limits.h      16 Oct 2005 15:32:33 -0000      1.12
+@@ -122,20 +123,20 @@
+ #if defined __GNUC__ && !defined _GCC_LIMITS_H_
+ /* `_GCC_LIMITS_H_' is what GCC's file defines.  */
+ # include_next <limits.h>
++#endif
+ /* The <limits.h> files in some gcc versions don't define LLONG_MIN,
+    LLONG_MAX, and ULLONG_MAX.  Instead only the values gcc defined for
+    ages are available.  */
+-# ifdef __USE_ISOC99
+-#  ifndef LLONG_MIN
+-#   define LLONG_MIN  LONG_LONG_MIN
+-#  endif
+-#  ifndef LLONG_MAX
+-#   define LLONG_MAX  LONG_LONG_MAX
+-#  endif
+-#  ifndef ULLONG_MAX
+-#   define ULLONG_MAX ULONG_LONG_MAX
+-#  endif
++#if defined __USE_ISOC99 && defined __GNUC__
++# ifndef LLONG_MIN
++#  define LLONG_MIN   (-LLONG_MAX-1)
++# endif
++# ifndef LLONG_MAX
++#  define LLONG_MAX   __LONG_LONG_MAX__
++# endif
++# ifndef ULLONG_MAX
++#  define ULLONG_MAX  (LLONG_MAX * 2ULL + 1)
+ # endif
+ #endif
diff --git a/src/patches/glibc/glibc-bz1230.patch b/src/patches/glibc/glibc-bz1230.patch
new file mode 100644 (file)
index 0000000..f95395f
--- /dev/null
@@ -0,0 +1,114 @@
+2005-09-27  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1230]
+       * stdlib/strtod_l.c (STRNCASECMP): Always use C locale object.
+       (TOLOWER_C): Define.  Use it when recognizing inf and nan.
+       * stdlib/Makefile (tests): Add bug-strtod2.
+       * stdlib/bug-strtod2.c: New file.
+
+--- libc/stdlib/strtod_l.c     10 Dec 2004 04:41:20 -0000      1.9
++++ libc/stdlib/strtod_l.c     28 Sep 2005 06:06:51 -0000      1.11
+@@ -100,7 +100,9 @@ extern unsigned long long int ____strtou
+ # define ISDIGIT(Ch) __iswdigit_l ((Ch), loc)
+ # define ISXDIGIT(Ch) __iswxdigit_l ((Ch), loc)
+ # define TOLOWER(Ch) __towlower_l ((Ch), loc)
+-# define STRNCASECMP(S1, S2, N) __wcsncasecmp_l ((S1), (S2), (N), loc)
++# define TOLOWER_C(Ch) __towlower_l ((Ch), &_nl_C_locobj)
++# define STRNCASECMP(S1, S2, N) \
++  __wcsncasecmp_l ((S1), (S2), (N), &_nl_C_locobj)
+ # define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, loc)
+ #else
+ # define STRING_TYPE char
+@@ -110,7 +112,9 @@ extern unsigned long long int ____strtou
+ # define ISDIGIT(Ch) __isdigit_l ((Ch), loc)
+ # define ISXDIGIT(Ch) __isxdigit_l ((Ch), loc)
+ # define TOLOWER(Ch) __tolower_l ((Ch), loc)
+-# define STRNCASECMP(S1, S2, N) __strncasecmp_l ((S1), (S2), (N), loc)
++# define TOLOWER_C(Ch) __tolower_l ((Ch), &_nl_C_locobj)
++# define STRNCASECMP(S1, S2, N) \
++  __strncasecmp_l ((S1), (S2), (N), &_nl_C_locobj)
+ # define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, loc)
+ #endif
+@@ -554,7 +558,7 @@ INTERNAL (__STRTOF) (nptr, endptr, group
+   else if (c < L_('0') || c > L_('9'))
+     {
+       /* Check for `INF' or `INFINITY'.  */
+-      if (TOLOWER (c) == L_('i') && STRNCASECMP (cp, L_("inf"), 3) == 0)
++      if (TOLOWER_C (c) == L_('i') && STRNCASECMP (cp, L_("inf"), 3) == 0)
+       {
+         /* Return +/- infinity.  */
+         if (endptr != NULL)
+@@ -565,7 +569,7 @@ INTERNAL (__STRTOF) (nptr, endptr, group
+         return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
+       }
+-      if (TOLOWER (c) == L_('n') && STRNCASECMP (cp, L_("nan"), 3) == 0)
++      if (TOLOWER_C (c) == L_('n') && STRNCASECMP (cp, L_("nan"), 3) == 0)
+       {
+         /* Return NaN.  */
+         FLOAT retval = NAN;
+--- libc/stdlib/Makefile       22 Jul 2005 04:25:44 -0000      1.101
++++ libc/stdlib/Makefile       28 Sep 2005 06:08:26 -0000      1.102
+@@ -63,7 +63,7 @@ tests                := tst-strtol tst-strtod testmb t
+                  test-canon test-canon2 tst-strtoll tst-environ           \
+                  tst-xpg-basename tst-random tst-random2 tst-bsearch      \
+                  tst-limits tst-rand48 bug-strtod tst-setcontext          \
+-                 test-a64l tst-qsort tst-system testmb2
++                 test-a64l tst-qsort tst-system testmb2 bug-strtod2
+ include ../Makeconfig
+--- libc/stdlib/bug-strtod2.c 1 Jan 1970 00:00:00 -0000
++++ libc/stdlib/bug-strtod2.c  28 Sep 2005 06:08:02 -0000      1.1
+@@ -0,0 +1,46 @@
++#include <locale.h>
++#include <math.h>
++#include <stdio.h>
++#include <stdlib.h>
++
++static const char *tests[] =
++  {
++    "inf", "Inf", "iNf", "inF", "INf", "iNF", "INF", "InF",
++    "infinity", "Infinity", "InfInity", "INFINITY"
++  };
++#define ntests (sizeof (tests) / sizeof (tests[0]))
++
++static int
++do_test (void)
++{
++  /* The Turkish locale is notorious because tolower() maps 'I' to the
++     dotless lowercase 'i' and toupper() maps 'i' to an 'I' with a dot
++     above.  */
++  if (setlocale (LC_ALL, "tr_TR.UTF-8") == NULL)
++    {
++      puts ("cannot set locale");
++      return 0;
++    }
++
++  int res = 0;
++  for (int i = 0; i < ntests; ++i)
++    {
++      char *endp;
++      double d = strtod (tests[i], &endp);
++      if (*endp != '\0')
++      {
++        printf ("did not consume all of '%s'\n", tests[i]);
++        res = 1;
++      }
++      if (!isinf (d))
++      {
++        printf ("'%s' does not pass isinf\n", tests[i]);
++        res = 1;
++      }
++    }
++
++  return res;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/stdlib/Depend 1 Jan 1970 00:00:00 -0000
++++ libc/stdlib/Depend 28 Sep 2005 05:51:29 -0000      1.1
+@@ -0,0 +1 @@
++localedata
diff --git a/src/patches/glibc/glibc-bz1346.patch b/src/patches/glibc/glibc-bz1346.patch
new file mode 100644 (file)
index 0000000..84077ca
--- /dev/null
@@ -0,0 +1,55 @@
+2005-09-20  Roland McGrath  <roland@redhat.com>
+
+       [BZ #1346]
+       * elf/dl-load.c (_dl_map_object_from_fd) [HAVE_Z_RELRO]: Do relro
+       magic on __stack_prot only if [SHARED].  Skip mprotect if __stack_prot
+       lies outside the page-rounded-down relro region.
+
+--- libc/elf/dl-load.c 2 Sep 2005 07:33:58 -0000       1.270
++++ libc/elf/dl-load.c 20 Sep 2005 07:46:12 -0000      1.271
+@@ -1314,22 +1314,37 @@ cannot allocate TLS data structures for 
+   if (__builtin_expect ((stack_flags &~ GL(dl_stack_flags)) & PF_X, 0))
+     {
++      if (__builtin_expect (__check_caller (RETURN_ADDRESS (0),
++                                           allow_ldso|allow_libc),
++                          0) != 0)
++      {
++        errstring = N_("invalid caller");
++        goto call_lose;
++      }
++
+       /* The stack is presently not executable, but this module
+        requires that it be executable.  We must change the
+        protection of the variable which contains the flags used in
+        the mprotect calls.  */
+-#ifdef HAVE_Z_RELRO
++#if defined HAVE_Z_RELRO && defined SHARED
+       if (mode & __RTLD_DLOPEN)
+       {
+-        uintptr_t p = ((uintptr_t) &__stack_prot) & ~(GLRO(dl_pagesize) - 1);
+-        size_t s = (uintptr_t) &__stack_prot - p + sizeof (int);
++        const uintptr_t p = (uintptr_t) &__stack_prot & -GLRO(dl_pagesize);
++        const size_t s = (uintptr_t) (&__stack_prot + 1) - p;
+-        __mprotect ((void *) p, s, PROT_READ|PROT_WRITE);
+-        if (__builtin_expect (__check_caller (RETURN_ADDRESS (0),
+-                                              allow_ldso|allow_libc) == 0,
+-                              0))
++        struct link_map *const m = &GL(dl_rtld_map);
++        const uintptr_t relro_end = ((m->l_addr + m->l_relro_addr
++                                      + m->l_relro_size)
++                                     & -GLRO(dl_pagesize));
++        if (__builtin_expect (p + s <= relro_end, 1))
++          {
++            /* The variable lies in the region protected by RELRO.  */
++            __mprotect ((void *) p, s, PROT_READ|PROT_WRITE);
++            __stack_prot |= PROT_READ|PROT_WRITE|PROT_EXEC;
++            __mprotect ((void *) p, s, PROT_READ);
++          }
++        else
+           __stack_prot |= PROT_READ|PROT_WRITE|PROT_EXEC;
+-        __mprotect ((void *) p, s, PROT_READ);
+       }
+       else
+ #endif
diff --git a/src/patches/glibc/glibc-bz1548.patch b/src/patches/glibc/glibc-bz1548.patch
new file mode 100644 (file)
index 0000000..30e7044
--- /dev/null
@@ -0,0 +1,18 @@
+2005-11-03  Roland McGrath  <roland@redhat.com>
+
+       [BZ #1548]
+       * sunrpc/svc.c (svc_getreqset): Use ffsl instead of ffs on fd_mask,
+       make sure constant is long.
+       From Jay Lan <jlan@engr.sgi.com>.
+
+--- libc/sunrpc/svc.c  9 Feb 2004 10:47:53 -0000       1.18
++++ libc/sunrpc/svc.c  3 Nov 2005 23:30:45 -0000       1.20
+@@ -372,7 +372,7 @@ svc_getreqset (fd_set *readfds)
+     setsize = FD_SETSIZE;
+   maskp = readfds->fds_bits;
+   for (sock = 0; sock < setsize; sock += NFDBITS)
+-    for (mask = *maskp++; (bit = ffs (mask)); mask ^= (1 << (bit - 1)))
++    for (mask = *maskp++; (bit = ffsl (mask)); mask ^= (1L << (bit - 1)))
+       INTUSE(svc_getreq_common) (sock + bit - 1);
+ }
+ INTDEF (svc_getreqset)
diff --git a/src/patches/glibc/glibc-bz1566.patch b/src/patches/glibc/glibc-bz1566.patch
new file mode 100644 (file)
index 0000000..84ae34e
--- /dev/null
@@ -0,0 +1,19 @@
+2005-12-23  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1566]
+       * sysdeps/i386/i586/memusage.h: New file.
+       * sysdeps/i386/memusage.h: Don't define GETTIME.
+
+--- libc/sysdeps/i386/memusage.h       6 Jul 2001 04:55:52 -0000       1.3
++++ libc/sysdeps/i386/memusage.h       23 Dec 2005 15:27:21 -0000      1.4
+@@ -17,6 +17,5 @@
+    02111-1307 USA.  */
+ #define GETSP() ({ register uintptr_t stack_ptr asm ("esp"); stack_ptr; })
+-#define GETTIME(low,high) asm ("rdtsc" : "=a" (low), "=d" (high))
+ #include <sysdeps/generic/memusage.h>
+--- libc/sysdeps/i386/i586/memusage.h  1 Jan 1970 00:00:00 -0000
++++ libc/sysdeps/i386/i586/memusage.h  23 Dec 2005 15:26:46 -0000      1.1
+@@ -0,0 +1 @@
++#include "../i686/memusage.h"
diff --git a/src/patches/glibc/glibc-bz1579.patch b/src/patches/glibc/glibc-bz1579.patch
new file mode 100644 (file)
index 0000000..40ae164
--- /dev/null
@@ -0,0 +1,17 @@
+2005-10-31  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1579]
+       * debug/execinfo.h: Change backtrace_symbols_fd comment.
+
+--- libc/debug/execinfo.h      22 Oct 2004 21:07:57 -0000      1.8
++++ libc/debug/execinfo.h      31 Oct 2005 15:25:14 -0000      1.9
+@@ -35,8 +35,7 @@ extern char **backtrace_symbols (void *_
+ /* This function is similar to backtrace_symbols() but it writes the result
+-   immediately to a file and can therefore also be used in situations where
+-   malloc() is not usable anymore.  */
++   immediately to a file.  */
+ extern void backtrace_symbols_fd (void *__const *__array, int __size, int __fd)
+      __THROW __nonnull ((1));
diff --git a/src/patches/glibc/glibc-bz1774.patch b/src/patches/glibc/glibc-bz1774.patch
new file mode 100644 (file)
index 0000000..48514c1
--- /dev/null
@@ -0,0 +1,43 @@
+2005-11-03  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1774]
+       * sysdeps/posix/getaddrinfo.c (gaih_inet): Don't use simple
+       gethostbyname2 lookup if AI_V4MAPPED|AI_ALL is set.
+
+       * sysdeps/posix/getaddrinfo.c (gaih_inet): Avoid alloca when possible
+       while looking for scope delimiter.
+
+--- libc/sysdeps/posix/getaddrinfo.c   26 Sep 2005 21:10:16 -0000      1.89
++++ libc/sysdeps/posix/getaddrinfo.c   3 Nov 2005 18:53:55 -0000       1.90
+@@ -568,12 +568,14 @@ gaih_inet (const char *name, const struc
+       if (at->family == AF_UNSPEC)
+       {
+-        char *namebuf = strdupa (name);
+-        char *scope_delim;
++        char *namebuf = (char *) name;
++        char *scope_delim = strchr (name, SCOPE_DELIMITER);
+-        scope_delim = strchr (namebuf, SCOPE_DELIMITER);
+-        if (scope_delim != NULL)
+-          *scope_delim = '\0';
++        if (__builtin_expect (scope_delim != NULL, 0))
++          {
++            namebuf = alloca (scope_delim - name + 1);
++            *((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0';
++          }
+         if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
+           {
+@@ -629,7 +631,10 @@ gaih_inet (const char *name, const struc
+         /* If we do not have to look for IPv4 and IPv6 together, use
+            the simple, old functions.  */
+-        if (req->ai_family == AF_INET || req->ai_family == AF_INET6)
++        if (req->ai_family == AF_INET
++            || (req->ai_family == AF_INET6
++                && ((req->ai_flags & AI_V4MAPPED) == 0
++                    || (req->ai_flags & AI_ALL) == 0)))
+           {
+             int family = req->ai_family;
+             size_t tmpbuflen = 512;
diff --git a/src/patches/glibc/glibc-bz1913.patch b/src/patches/glibc/glibc-bz1913.patch
new file mode 100644 (file)
index 0000000..a37223b
--- /dev/null
@@ -0,0 +1,26 @@
+2005-12-22  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1913]
+       * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S (__new_sem_wait):
+       Fix unwind info.  Remove useless branch prediction prefix.
+
+--- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S     26 Jan 2005 19:57:25 -0000      1.6
++++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S     22 Dec 2005 17:58:29 -0000      1.7
+@@ -57,7 +57,7 @@ __new_sem_wait:
+       cfi_offset(6, -12)              /* %esi */
+ 3:    movl    (%ebx), %eax
+ 2:    testl   %eax, %eax
+-      je,pn   1f
++      je      1f
+       leal    -1(%eax), %edx
+       LOCK
+@@ -73,7 +73,7 @@ __new_sem_wait:
+       cfi_adjust_cfa_offset(-12)
+       ret
+-      cfi_adjust_cfa_offset(8)
++      cfi_adjust_cfa_offset(12)
+       cfi_offset(3, -8)               /* %ebx */
+       cfi_offset(6, -12)              /* %esi */
+ 1:    call    __pthread_enable_asynccancel
diff --git a/src/patches/glibc/glibc-bz1920.patch b/src/patches/glibc/glibc-bz1920.patch
new file mode 100644 (file)
index 0000000..090345f
--- /dev/null
@@ -0,0 +1,52 @@
+2005-11-24  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
+       (__cleanup_fct_attribute): Use __regparm__ not regparm.
+
+       * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: When
+       compiling 32-bit code we must define __cleanup_fct_attribute.
+
+005-11-24  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #1920]
+       * sysdeps/pthread/pthread.h (__pthread_unwind_next): Use
+       __attribute__ instead of __attribute.
+       * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
+       (__cleanup_fct_attribute): Likewise.
+
+--- libc/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h 28 Sep 2004 10:27:49 -0000      1.17
++++ libc/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h 24 Nov 2005 18:27:08 -0000      1.19
+@@ -155,6 +155,6 @@ typedef union
+ /* Extra attributes for the cleanup functions.  */
+-#define __cleanup_fct_attribute __attribute ((regparm (1)))
++#define __cleanup_fct_attribute __attribute__ ((__regparm__ (1)))
+ #endif        /* bits/pthreadtypes.h */
+--- libc/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h       6 Oct 2004 18:05:42 -0000       1.20
++++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h       24 Nov 2005 18:25:32 -0000      1.21
+@@ -192,4 +192,9 @@ typedef union
+ #endif
++#if __WORDSIZE == 32
++/* Extra attributes for the cleanup functions.  */
++# define __cleanup_fct_attribute __attribute__ ((__regparm__ (1)))
++#endif
++
+ #endif        /* bits/pthreadtypes.h */
+--- libc/nptl/sysdeps/pthread/pthread.h        11 Jul 2005 16:38:01 -0000      1.34
++++ libc/nptl/sysdeps/pthread/pthread.h        24 Nov 2005 18:15:53 -0000      1.35
+@@ -657,9 +657,9 @@ extern void __pthread_unregister_cancel_
+ /* Internal interface to initiate cleanup.  */
+ extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf)
+-     __cleanup_fct_attribute __attribute ((__noreturn__))
++     __cleanup_fct_attribute __attribute__ ((__noreturn__))
+ # ifndef SHARED
+-     __attribute ((__weak__))
++     __attribute__ ((__weak__))
+ # endif
+      ;
+ #endif
diff --git a/src/patches/glibc/glibc-bz1925.patch b/src/patches/glibc/glibc-bz1925.patch
new file mode 100644 (file)
index 0000000..d6d8b72
--- /dev/null
@@ -0,0 +1,16 @@
+2005-11-25  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1925]
+       * nis/ypclnt.c (yp_order): Correct test for invalid parameter.
+
+--- libc/nis/ypclnt.c  24 Mar 2005 00:16:58 -0000      1.51
++++ libc/nis/ypclnt.c  25 Nov 2005 16:04:44 -0000      1.52
+@@ -593,7 +593,7 @@ yp_order (const char *indomain, const ch
+   enum clnt_stat result;
+   if (indomain == NULL || indomain[0] == '\0' ||
+-      inmap == NULL || inmap == '\0')
++      inmap == NULL || inmap[0] == '\0')
+     return YPERR_BADARGS;
+   req.domain = (char *) indomain;
diff --git a/src/patches/glibc/glibc-bz1951.patch b/src/patches/glibc/glibc-bz1951.patch
new file mode 100644 (file)
index 0000000..f60406a
--- /dev/null
@@ -0,0 +1,253 @@
+2006-04-23  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1951]
+       * sysdeps/posix/sigset.c (sigset): Return correct value reflecting
+       previous signal state.
+       * signal/Makefile (tests): Add tst-sigset2.
+       * signal/tst-sigset2.c: New file.
+
+--- libc/sysdeps/posix/sigset.c        17 Jun 2005 22:47:23 -0000      1.7
++++ libc/sysdeps/posix/sigset.c        23 Apr 2006 19:04:13 -0000      1.8
+@@ -29,8 +29,10 @@ sigset (sig, disp)
+      int sig;
+      __sighandler_t disp;
+ {
+-  struct sigaction act, oact;
++  struct sigaction act;
++  struct sigaction oact;
+   sigset_t set;
++  sigset_t oset;
+ #ifdef SIG_HOLD
+   /* Handle SIG_HOLD first.  */
+@@ -45,10 +47,18 @@ sigset (sig, disp)
+       return SIG_ERR;
+       /* Add the signal set to the current signal mask.  */
+-      if (__sigprocmask (SIG_BLOCK, &set, NULL) < 0)
++      if (__sigprocmask (SIG_BLOCK, &set, &oset) < 0)
+       return SIG_ERR;
+-      return SIG_HOLD;
++      /* If the signal was already blocked signal this to the caller.  */
++      if (__sigismember (&oset, sig))
++      return SIG_HOLD;
++
++      /* We need to determine whether a specific handler is installed.  */
++      if (__sigaction (sig, NULL, &oact) < 0)
++      return SIG_ERR;
++
++      return oact.sa_handler;
+     }
+ #endif        /* SIG_HOLD */
+@@ -75,8 +85,9 @@ sigset (sig, disp)
+     return SIG_ERR;
+   /* Remove the signal set from the current signal mask.  */
+-  if (__sigprocmask (SIG_UNBLOCK, &set, NULL) < 0)
++  if (__sigprocmask (SIG_UNBLOCK, &set, &oset) < 0)
+     return SIG_ERR;
+-  return oact.sa_handler;
++  /* If the signal was already blocked return SIG_HOLD.  */
++  return __sigismember (&oset, sig) ? SIG_HOLD : oact.sa_handler;
+ }
+--- libc/signal/Makefile       29 Dec 2003 17:49:12 -0000      1.24
++++ libc/signal/Makefile       23 Apr 2006 19:03:28 -0000      1.25
+@@ -38,7 +37,7 @@ routines     := signal raise killpg \
+                  allocrtsig sigtimedwait sigwaitinfo sigqueue \
+                  sighold sigrelse sigignore sigset
+-tests         := tst-signal tst-sigset tst-sigsimple tst-raise
++tests         := tst-signal tst-sigset tst-sigsimple tst-raise tst-sigset2
+ distribute    := sigsetops.h testrtsig.h sigset-cvt-mask.h
+--- libc/signal/tst-sigset2.c  1 Jan 1970 00:00:00 -0000
++++ libc/signal/tst-sigset2.c  23 Apr 2006 19:03:05 -0000      1.1
+@@ -0,0 +1,184 @@
++/* sigset_SIG_HOLD_bug.c [BZ #1951] */
++#include <errno.h>
++#include <error.h>
++#include <inttypes.h>
++#include <signal.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++
++#define TEST_SIG SIGINT
++
++
++/* Print mask of blocked signals for this process */
++static void
++printSigMask (const char *msg)
++{
++  sigset_t currMask;
++  int sig;
++  int cnt;
++
++  if (msg != NULL)
++    printf ("%s", msg);
++
++  if (sigprocmask (SIG_BLOCK, NULL, &currMask) == -1)
++    error (1, errno, "sigaction");
++
++  cnt = 0;
++  for (sig = 1; sig < NSIG; sig++)
++    {
++      if (sigismember (&currMask, sig))
++      {
++        cnt++;
++        printf ("\t\t%d (%s)\n", sig, strsignal (sig));
++        }
++    }
++
++  if (cnt == 0)
++    printf ("\t\t<empty signal set>\n");
++} /* printSigMask */
++
++static void
++handler (int sig)
++{
++  printf ("Caught signal %d\n", sig);
++  printSigMask ("Signal mask in handler\n");
++  printf ("Handler returning\n");
++  _exit (1);
++} /* handler */
++
++static void
++printDisposition (sighandler_t disp)
++{
++  if (disp == SIG_HOLD)
++    printf ("SIG_HOLD");
++  else if (disp == SIG_DFL)
++    printf ("SIG_DFL");
++  else if (disp == SIG_IGN)
++    printf ("SIG_IGN");
++  else
++    printf ("handled at %" PRIxPTR, (uintptr_t) disp);
++} /* printDisposition */
++
++static int
++returnTest1 (void)
++{
++  sighandler_t prev;
++
++  printf ("===== TEST 1 =====\n");
++  printf ("Blocking signal with sighold()\n");
++  if (sighold (TEST_SIG) == -1)
++    error (1, errno, "sighold");
++  printSigMask ("Signal mask after sighold()\n");
++
++  printf ("About to use sigset() to establish handler\n");
++  prev = sigset (TEST_SIG, handler);
++  if (prev == SIG_ERR)
++    error(1, errno, "sigset");
++
++  printf ("Previous disposition: ");
++  printDisposition (prev);
++  printf (" (should be SIG_HOLD)\n");
++  if (prev != SIG_HOLD)
++    {
++      printf("TEST FAILED!!!\n");
++      return 1;
++    }
++  return 0;
++} /* returnTest1 */
++
++static int
++returnTest2 (void)
++{
++  sighandler_t prev;
++
++  printf ("\n===== TEST 2 =====\n");
++
++  printf ("About to use sigset() to set SIG_HOLD\n");
++  prev = sigset (TEST_SIG, SIG_HOLD);
++  if (prev == SIG_ERR)
++    error (1, errno, "sigset");
++
++  printf ("Previous disposition: ");
++  printDisposition (prev);
++  printf (" (should be SIG_DFL)\n");
++  if (prev != SIG_DFL)
++    {
++      printf("TEST FAILED!!!\n");
++      return 1;
++    }
++  return 0;
++} /* returnTest2 */
++
++static int
++returnTest3 (void)
++{
++  sighandler_t prev;
++
++  printf ("\n===== TEST 3 =====\n");
++
++  printf ("About to use sigset() to set SIG_HOLD\n");
++  prev = sigset (TEST_SIG, SIG_HOLD);
++  if (prev == SIG_ERR)
++    error (1, errno, "sigset");
++
++  printf ("About to use sigset() to set SIG_HOLD (again)\n");
++  prev = sigset (TEST_SIG, SIG_HOLD);
++  if (prev == SIG_ERR)
++    error (1, errno, "sigset");
++
++  printf ("Previous disposition: ");
++  printDisposition (prev);
++  printf (" (should be SIG_HOLD)\n");
++  if (prev != SIG_HOLD)
++    {
++      printf("TEST FAILED!!!\n");
++      return 1;
++    }
++  return 0;
++} /* returnTest3 */
++
++int
++main (int argc, char *argv[])
++{
++  pid_t childPid;
++
++  childPid = fork();
++  if (childPid == -1)
++    error (1, errno, "fork");
++
++  if (childPid == 0)
++    exit (returnTest1 ());
++
++  int status;
++  if (TEMP_FAILURE_RETRY (waitpid (childPid, &status, 0)) != childPid)
++    error (1, errno, "waitpid");
++  int result = !WIFEXITED (status) || WEXITSTATUS (status) != 0;
++
++  childPid = fork();
++  if (childPid == -1)
++    error (1, errno, "fork");
++
++  if (childPid == 0)
++    exit (returnTest2 ());
++
++  if (TEMP_FAILURE_RETRY (waitpid (childPid, &status, 0)) != childPid)
++    error (1, errno, "waitpid");
++  result |= !WIFEXITED (status) || WEXITSTATUS (status) != 0;
++
++  childPid = fork();
++  if (childPid == -1)
++    error (1, errno, "fork");
++
++  if (childPid == 0)
++    exit (returnTest3 ());
++
++  if (TEMP_FAILURE_RETRY (waitpid (childPid, &status, 0)) != childPid)
++    error (1, errno, "waitpid");
++  result |= !WIFEXITED (status) || WEXITSTATUS (status) != 0;
++
++  return result;
++} /* main */
diff --git a/src/patches/glibc/glibc-bz1952.patch b/src/patches/glibc/glibc-bz1952.patch
new file mode 100644 (file)
index 0000000..f8932f6
--- /dev/null
@@ -0,0 +1,65 @@
+2005-12-20  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/time.c: If __NR_time is not defined,
+       use sysdeps/unix/time.c implementation.
+
+2005-12-19  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1952]
+       * sysdeps/unix/sysv/linux/time.c: New file.
+       * sysdeps/unix/sysv/linux/i386/syscalls.list: Remove time entry.
+
+--- libc/sysdeps/unix/sysv/linux/time.c        1 Jan 1970 00:00:00 -0000
++++ libc/sysdeps/unix/sysv/linux/time.c        20 Dec 2005 14:57:37 -0000      1.2
+@@ -0,0 +1,43 @@
++/* Copyright (C) 2005 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 <stddef.h>
++#include <time.h>
++
++#include <sysdep.h>
++
++#ifdef __NR_time
++
++time_t
++time (t)
++     time_t *t;
++{
++  INTERNAL_SYSCALL_DECL (err);
++  time_t res = INTERNAL_SYSCALL (time, err, 1, NULL);
++  /* There cannot be any error.  */
++  if (t != NULL)
++    *t = res;
++  return res;
++}
++libc_hidden_def (time)
++
++#else
++
++# include <sysdeps/unix/time.c>
++
++#endif
+--- libc/sysdeps/unix/sysv/linux/i386/syscalls.list    10 Mar 2004 08:38:15 -0000      1.19
++++ libc/sysdeps/unix/sysv/linux/i386/syscalls.list    20 Dec 2005 07:52:13 -0000      1.20
+@@ -5,5 +5,4 @@ vm86old                EXTRA   vm86old         i:p     __vm86old       vm
+ vm86          -       vm86            i:ip    __vm86          vm86@@GLIBC_2.3.4
+ oldgetrlimit  EXTRA   getrlimit       i:ip    __old_getrlimit getrlimit@GLIBC_2.0
+ oldsetrlimit  EXTRA   setrlimit       i:ip    __old_setrlimit setrlimit@GLIBC_2.0
+-time          -       time            Ei:p    time
+ waitpid               -       waitpid         Ci:ipi  __waitpid       waitpid __libc_waitpid
diff --git a/src/patches/glibc/glibc-bz1955.patch b/src/patches/glibc/glibc-bz1955.patch
new file mode 100644 (file)
index 0000000..70b09d5
--- /dev/null
@@ -0,0 +1,17 @@
+2005-12-19  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1955]
+       * timezone/zic.c (tofile;): Fix typo in symlink creation.
+       Patch by Phil Estes <pestes@us.ibm.com>.
+
+--- libc/timezone/zic.c        6 Aug 2005 05:40:57 -0000       1.20
++++ libc/timezone/zic.c        20 Dec 2005 07:55:45 -0000      1.21
+@@ -650,7 +650,7 @@ const char * const tofile;
+                                               "../");
+                                       symlinkcontents =
+                                               ecatalloc(symlinkcontents,
+-                                              fromfile);
++                                                        fromname);
+                                       result = symlink(symlinkcontents,
+                                               toname);
+                                       if (result == 0)
diff --git a/src/patches/glibc/glibc-bz1962.patch b/src/patches/glibc/glibc-bz1962.patch
new file mode 100644 (file)
index 0000000..16abba0
--- /dev/null
@@ -0,0 +1,67 @@
+2005-12-21  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1962]
+       * io/fts.c (fts_open): Change type of len to size_t.
+       (fts_build): Remove cast in call to fts_alloc.
+       (fts_alloc): Change third parameter's type to size_t.
+
+       [BZ #1960]
+       * io/fts.c (fts_open): Avoid function call in MAX macro use.
+
+--- libc/io/fts.c      14 Sep 2004 04:24:44 -0000      1.29
++++ libc/io/fts.c      21 Dec 2005 08:33:31 -0000      1.31
+@@ -53,7 +53,7 @@ static char sccsid[] = "@(#)fts.c    8.6 (B
+ #endif
+-static FTSENT *fts_alloc (FTS *, const char *, int) internal_function;
++static FTSENT *fts_alloc (FTS *, const char *, size_t) internal_function;
+ static FTSENT *fts_build (FTS *, int) internal_function;
+ static void    fts_lfree (FTSENT *) internal_function;
+ static void    fts_load (FTS *, FTSENT *) internal_function;
+@@ -94,7 +94,6 @@ fts_open(argv, options, compar)
+       register FTSENT *p, *root;
+       register int nitems;
+       FTSENT *parent, *tmp;
+-      int len;
+       /* Options check. */
+       if (options & ~FTS_OPTIONMASK) {
+@@ -120,7 +119,8 @@ fts_open(argv, options, compar)
+ #ifndef MAXPATHLEN
+ #define MAXPATHLEN 1024
+ #endif
+-      if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
++      size_t maxarglen = fts_maxarglen(argv);
++      if (fts_palloc(sp, MAX(maxarglen, MAXPATHLEN)))
+               goto mem1;
+       /* Allocate/initialize root's parent. */
+@@ -131,7 +131,8 @@ fts_open(argv, options, compar)
+       /* Allocate/initialize root(s). */
+       for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
+               /* Don't allow zero-length paths. */
+-              if ((len = strlen(*argv)) == 0) {
++              size_t len = strlen(*argv);
++              if (len == 0) {
+                       __set_errno (ENOENT);
+                       goto mem3;
+               }
+@@ -690,7 +691,7 @@ fts_build(sp, type)
+               if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
+                       continue;
+-              if ((p = fts_alloc(sp, dp->d_name, (int)_D_EXACT_NAMLEN (dp))) == NULL)
++              if ((p = fts_alloc(sp, dp->d_name, _D_EXACT_NAMLEN (dp))) == NULL)
+                       goto mem1;
+               if (_D_EXACT_NAMLEN (dp) >= maxlen) {/* include space for NUL */
+                       oldaddr = sp->fts_path;
+@@ -961,7 +962,7 @@ internal_function
+ fts_alloc(sp, name, namelen)
+       FTS *sp;
+       const char *name;
+-      register int namelen;
++      size_t namelen;
+ {
+       register FTSENT *p;
+       size_t len;
diff --git a/src/patches/glibc/glibc-bz1978.patch b/src/patches/glibc/glibc-bz1978.patch
new file mode 100644 (file)
index 0000000..36ad546
--- /dev/null
@@ -0,0 +1,55 @@
+2005-12-16  Thorsten Kukuk  <kukuk@suse.de>
+
+       [BZ #1978]
+       * sysdeps/unix/sysv/linux/internal_statvfs.c (__statvfs_getflags):
+       Map more filesystem types to a string.
+       * sysdeps/unix/sysv/linux/linux_fsinfo.h: Add SYSFS_MAGIC.
+
+--- libc/sysdeps/unix/sysv/linux/internal_statvfs.c    3 Apr 2004 17:32:18 -0000       1.13
++++ libc/sysdeps/unix/sysv/linux/internal_statvfs.c    20 Dec 2005 07:20:16 -0000      1.14
+@@ -71,6 +71,33 @@ __statvfs_getflags (const char *name, in
+     case NFS_SUPER_MAGIC:
+       fsname = "nfs";
+       break;
++    case SYSFS_MAGIC:
++      fsname = "sysfs";
++      break;
++    case REISERFS_SUPER_MAGIC:
++      fsname = "reiserfs";
++      break;
++    case XFS_SUPER_MAGIC:
++      fsname = "xfs";
++      break;
++    case JFS_SUPER_MAGIC:
++      fsname = "jfs";
++      break;
++    case HPFS_SUPER_MAGIC:
++      fsname = "hpfs";
++      break;
++    case DEVFS_SUPER_MAGIC:
++      fsname = "devfs";
++      break;
++    case ISOFS_SUPER_MAGIC:
++      fsname = "iso9660";
++      break;
++    case MSDOS_SUPER_MAGIC:
++      fsname = "msdos";
++      break;
++    case NTFS_SUPER_MAGIC:
++      fsname = "ntfs";
++      break;
+     }
+   FILE *mtab = __setmntent ("/proc/mounts", "r");
+--- libc/sysdeps/unix/sysv/linux/linux_fsinfo.h        17 Sep 2003 00:48:25 -0000      1.14
++++ libc/sysdeps/unix/sysv/linux/linux_fsinfo.h        20 Dec 2005 07:21:14 -0000      1.15
+@@ -135,6 +135,9 @@
+ /* Constants that identify the `vxfs' filesystem.  */
+ #define VXFS_SUPER_MAGIC      0xa501fcf5
++/* Constants that identify the `sysfs´ filesystem.  */
++#define SYSFS_MAGIC           0x62656572
++
+ /* Maximum link counts.  */
+ #define COH_LINK_MAX          10000
+ #define EXT2_LINK_MAX         32000
diff --git a/src/patches/glibc/glibc-bz2013.patch b/src/patches/glibc/glibc-bz2013.patch
new file mode 100644 (file)
index 0000000..0d892bf
--- /dev/null
@@ -0,0 +1,81 @@
+2006-01-05  H.J. Lu  <hongjiu.lu@intel.com>
+
+       [BZ #2013]
+       * sysdeps/ia64/memccpy.S: Properly handle recovery for
+       predicated speculative load.
+
+--- libc/sysdeps/ia64/memccpy.S        19 Nov 2003 06:11:26 -0000      1.7
++++ libc/sysdeps/ia64/memccpy.S        2 Mar 2006 04:49:27 -0000       1.8
+@@ -183,27 +183,64 @@ ENTRY(memccpy)
+       br.ret.sptk.many b0
+ .recovery1:
+-      adds    src = -(MEMLAT + 6 + 1) * 8, asrc
++#if MEMLAT != 6
++# error "MEMLAT must be 6!"
++#endif
++      adds    src = -8, asrc
+       mov     loopcnt = ar.lc
+-      mov     tmp = ar.ec ;;
++      mov     tmp = ar.ec
++      ;;
++(p[0])        adds    src = -8, src
++      ;;
++(p[1])        adds    src = -8, src
+       sub     sh1 = (MEMLAT + 6 + 1), tmp
+-      shr.u   sh2 = sh2, 3
+-      ;; 
++      ;;
++(p[2])        adds    src = -8, src
++      ;;
++(p[3])        adds    src = -8, src
+       shl     loopcnt = loopcnt, 3
+-      sub     src = src, sh2
++      ;;
++(p[4])        adds    src = -8, src
++      ;;
++(p[5])        adds    src = -8, src
+       shl     sh1 = sh1, 3
++      ;;
++(p[6])        adds    src = -8, src
++      ;;
++(p[7])        adds    src = -8, src
+       shl     tmp = tmp, 3
+       ;;
++(p[8])        adds    src = -8, src
++      ;;
++(p[9])        adds    src = -8, src
++      shr.u   sh2 = sh2, 3
++      ;;
++(p[10])       adds    src = -8, src
++      ;;
++(p[11])       adds    src = -8, src
+       add     len = len, loopcnt
+-      add     src = sh1, src ;;
++      ;;
++      sub     src = src, sh2
++      ;;
+       add     len = tmp, len
+-.back1:
++      add     src = sh1, src
+       br.cond.sptk .cpyfew
+ .recovery2:
+-      add     tmp = -(MEMLAT + 3) * 8, src
++#if MEMLAT != 6
++# error "MEMLAT must be 6!"
++#endif
++      add     tmp = -8, src
+ (p7)  br.cond.spnt .gotit
+       ;;
++(p[0])        add     tmp = -8, tmp ;;
++(p[1])        add     tmp = -8, tmp ;;
++(p[2])        add     tmp = -8, tmp ;;
++(p[3])        add     tmp = -8, tmp ;;
++(p[4])        add     tmp = -8, tmp ;;
++(p[5])        add     tmp = -8, tmp ;;
++(p[6])        add     tmp = -8, tmp ;;
++(p[7])        add     tmp = -8, tmp ;;
+       ld8     r[MEMLAT+2] = [tmp] ;;
+       xor     pos0[1] = r[MEMLAT+2], charx8 ;;
+       czx1.r  pos0[1] = pos0[1] ;;
diff --git a/src/patches/glibc/glibc-bz2066.patch b/src/patches/glibc/glibc-bz2066.patch
new file mode 100644 (file)
index 0000000..0e267de
--- /dev/null
@@ -0,0 +1,20 @@
+2005-12-21  Roland McGrath  <roland@redhat.com>
+
+       [BZ #2066]
+       * intl/l10nflist.c (_nl_make_l10nflist): Free ABS_FILENAME when later
+       malloc fails.
+
+--- libc/intl/l10nflist.c      26 Sep 2004 05:06:25 -0000      1.32
++++ libc/intl/l10nflist.c      22 Dec 2005 01:03:27 -0000      1.33
+@@ -270,7 +270,10 @@ _nl_make_l10nflist (l10nfile_list, dirli
+                               * (1 << pop (mask))
+                               * sizeof (struct loaded_l10nfile *)));
+   if (retval == NULL)
+-    return NULL;
++    {
++      free (abs_filename);
++      return NULL;
++    }
+   retval->filename = abs_filename;
+   /* If more than one directory is in the list this is a pseudo-entry
diff --git a/src/patches/glibc/glibc-bz2072.patch b/src/patches/glibc/glibc-bz2072.patch
new file mode 100644 (file)
index 0000000..3522f65
--- /dev/null
@@ -0,0 +1,84 @@
+2006-04-25  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2072]
+       * stdio-common/printf_fp.c: Fix potential memory leaks for
+       malloc'ed wbuffer which isn't freed in error conditions.
+
+--- libc/stdio-common/printf_fp.c      14 Jan 2006 12:09:45 -0000      1.57
++++ libc/stdio-common/printf_fp.c      25 Apr 2006 18:38:30 -0000      1.58
+@@ -72,7 +72,11 @@
+     {                                                                       \
+       register const int outc = (ch);                                       \
+       if (putc (outc, fp) == EOF)                                           \
+-      return -1;                                                            \
++      {                                                                     \
++        if (buffer_malloced)                                                \
++          free (wbuffer);                                                   \
++        return -1;                                                          \
++      }                                                                     \
+       ++done;                                                               \
+     } while (0)
+@@ -83,7 +87,11 @@
+       if (len > 20)                                                         \
+       {                                                                     \
+         if (PUT (fp, wide ? (const char *) wptr : ptr, outlen) != outlen)   \
+-          return -1;                                                        \
++          {                                                                 \
++            if (buffer_malloced)                                            \
++              free (wbuffer);                                               \
++            return -1;                                                      \
++          }                                                                 \
+         ptr += outlen;                                                      \
+         done += outlen;                                                     \
+       }                                                                     \
+@@ -102,7 +110,11 @@
+   do                                                                        \
+     {                                                                       \
+       if (PAD (fp, ch, len) != len)                                         \
+-      return -1;                                                            \
++      {                                                                     \
++        if (buffer_malloced)                                                \
++          free (wbuffer);                                                   \
++        return -1;                                                          \
++      }                                                                     \
+       done += len;                                                          \
+     }                                                                       \
+   while (0)
+@@ -200,6 +212,11 @@ ___printf_fp (FILE *fp,
+   /* Nonzero if this is output on a wide character stream.  */
+   int wide = info->wide;
++  /* Buffer in which we produce the output.  */
++  wchar_t *wbuffer = NULL;
++  /* Flag whether wbuffer is malloc'ed or not.  */
++  int buffer_malloced = 0;
++
+   auto wchar_t hack_digit (void);
+   wchar_t hack_digit (void)
+@@ -790,8 +807,7 @@ ___printf_fp (FILE *fp,
+   {
+     int width = info->width;
+-    wchar_t *wbuffer, *wstartp, *wcp;
+-    int buffer_malloced;
++    wchar_t *wstartp, *wcp;
+     int chars_needed;
+     int expscale;
+     int intdig_max, intdig_no = 0;
+@@ -1109,8 +1125,12 @@ ___printf_fp (FILE *fp,
+             buffer = (char *) malloc (2 + chars_needed + decimal_len
+                                       + ngroups * thousands_sep_len);
+             if (buffer == NULL)
+-              /* Signal an error to the caller.  */
+-              return -1;
++              {
++                /* Signal an error to the caller.  */
++                if (buffer_malloced)
++                  free (wbuffer);
++                return -1;
++              }
+           }
+         else
+           buffer = (char *) alloca (2 + chars_needed + decimal_len
diff --git a/src/patches/glibc/glibc-bz2080.patch b/src/patches/glibc/glibc-bz2080.patch
new file mode 100644 (file)
index 0000000..98ead60
--- /dev/null
@@ -0,0 +1,19 @@
+2005-12-30  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2080]
+       * libio/iogetwline.c (_IO_getwline_info): Move return to correct
+       location.
+
+--- libc/libio/iogetwline.c    26 Feb 2002 01:43:50 -0000      1.7
++++ libc/libio/iogetwline.c    30 Dec 2005 18:06:43 -0000      1.8
+@@ -87,9 +87,9 @@ _IO_getwline_info (fp, buf, n, delim, ex
+               *ptr++ = wc;
+             else if (extract_delim < 0)
+               INTUSE(_IO_sputbackc) (fp, wc);
+-            return ptr - buf;
+             if (extract_delim > 0)
+               ++len;
++            return ptr - buf;
+           }
+         *ptr++ = wc;
+         n--;
diff --git a/src/patches/glibc/glibc-bz2126.patch b/src/patches/glibc/glibc-bz2126.patch
new file mode 100644 (file)
index 0000000..aee4879
--- /dev/null
@@ -0,0 +1,118 @@
+2006-01-09  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2126]
+       * sysdeps/i386/i686/strtok.S: Store pointer to NUL byte if NULL is
+       returned.
+       * sysdeps/i386/strtok.S: Likewise.
+       * sysdeps/x86_64/strtok.S: Likewise.
+       * string/Makefile (tests): Add bug-strtok1.
+       * string/bug-strtok1.c: New file.
+
+--- libc/sysdeps/i386/strtok.S 4 May 2005 17:52:10 -0000       1.14
++++ libc/sysdeps/i386/strtok.S 10 Jan 2006 00:22:31 -0000      1.15
+@@ -385,6 +385,10 @@ L(epilogue):
+ L(returnNULL):
+       xorl %eax, %eax
++#ifdef USE_AS_STRTOK_R
++      movl SAVE(%esp), %ecx
++#endif
++      movl %edx, SAVE_PTR
+       RETURN_NULL_BOUNDED_POINTER
+       jmp L(epilogue)
+--- libc/sysdeps/i386/i686/strtok.S    4 May 2005 06:21:50 -0000       1.8
++++ libc/sysdeps/i386/i686/strtok.S    10 Jan 2006 00:23:13 -0000      1.9
+@@ -250,9 +250,9 @@ L(8):      cmpl %eax, %edx
+       cmovne %ecx, %edx
+       /* Store the pointer to the next character.  */
+-# ifdef USE_AS_STRTOK_R
++#ifdef USE_AS_STRTOK_R
+       movl SAVE(%esp), %ecx
+-# endif
++#endif
+       movl %edx, SAVE_PTR
+       CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb)
+       RETURN_BOUNDED_POINTER (SAVE_PTR)
+@@ -271,6 +271,10 @@ L(epilogue):
+ L(returnNULL):
+       xorl %eax, %eax
++#ifdef USE_AS_STRTOK_R
++      movl SAVE(%esp), %ecx
++#endif
++      movl %edx, SAVE_PTR
+       RETURN_NULL_BOUNDED_POINTER
+       jmp L(epilogue)
+--- libc/sysdeps/x86_64/strtok.S       31 Mar 2005 10:00:13 -0000      1.3
++++ libc/sysdeps/x86_64/strtok.S       10 Jan 2006 00:12:59 -0000      1.4
+@@ -205,6 +205,8 @@ L(epilogue):
+ L(returnNULL):
+       xorq %rax, %rax
++      /* Store the pointer to the next character.  */
++      movq %rdx, SAVE_PTR
+       jmp L(epilogue)
+ END (BP_SYM (FUNCTION))
+--- libc/string/bug-strtok1.c 1 Jan 1970 00:00:00 -0000
++++ libc/string/bug-strtok1.c  10 Jan 2006 00:12:13 -0000      1.1
+@@ -0,0 +1,45 @@
++/* See BZ #2126.  */
++#include <string.h>
++#include <stdio.h>
++
++static int
++do_test (void)
++{
++  const char str[] = "axaaba";
++  char *token;
++  char *cp;
++  char *l;
++  int result = 0;
++
++  puts ("test strtok");
++  cp = strdupa (str);
++  printf ("cp = %p, len = %zu\n", cp, strlen (cp));
++  token = strtok (cp, "ab");
++  result |= token == NULL || strcmp (token, "x");
++  printf ("token: %s (%d)\n", token ? token : "NULL", result);
++  token = strtok(0, "ab");
++  result |= token != NULL;
++  printf ("token: %s (%d)\n", token ? token : "NULL", result);
++  token = strtok(0, "a");
++  result |= token != NULL;
++  printf ("token: %s (%d)\n", token ? token : "NULL", result);
++
++  puts ("test strtok_r");
++  cp = strdupa (str);
++  size_t len = strlen (cp);
++  printf ("cp = %p, len = %zu\n", cp, len);
++  token = strtok_r (cp, "ab", &l);
++  result |= token == NULL || strcmp (token, "x");
++  printf ("token: %s, next = %p (%d)\n", token ? token : "NULL", l, result);
++  token = strtok_r(0, "ab", &l);
++  result |= token != NULL || l != cp + len;
++  printf ("token: %s, next = %p (%d)\n", token ? token : "NULL", l, result);
++  token = strtok_r(0, "a", &l);
++  result |= token != NULL || l != cp + len;
++  printf ("token: %s,  next = %p (%d)\n", token ? token : "NULL", l, result);
++
++  return result;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/string/Makefile       12 Apr 2005 15:27:59 -0000      1.66
++++ libc/string/Makefile       10 Jan 2006 00:11:53 -0000      1.67
+@@ -53,7 +53,7 @@ tests                := tester inl-tester noinl-tester
+                  tst-strlen stratcliff tst-svc tst-inlcall            \
+                  bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap      \
+                  tst-strtok tst-strxfrm bug-strcoll1 tst-strfry       \
+-                 $(addprefix test-,$(strop-tests))
++                 bug-strtok1 $(addprefix test-,$(strop-tests))
+ distribute    := memcopy.h pagecopy.h tst-svc.expect test-string.h
diff --git a/src/patches/glibc/glibc-bz2153.patch b/src/patches/glibc/glibc-bz2153.patch
new file mode 100644 (file)
index 0000000..1961167
--- /dev/null
@@ -0,0 +1,281 @@
+2006-01-15  Andreas Jaeger  <aj@suse.de>
+
+       [BZ #2153]
+       * sysdeps/generic/s_cacosh.c (__cacosh): Do not return a negative
+       value. Patch by Wes Loewer <wjltemp-temp01@yahoo.com>.
+       * sysdeps/generic/s_cacoshl.c (__cacoshl): Likewise.
+       * sysdeps/generic/s_cacoshf.c (__cacoshf): Likewise.
+       * math/libm-test.inc (cacosh_test): Adjust for change.
+
+       * sysdeps/alpha/fpu/libm-test-ulps: Adopt for cacosh test change.
+       * sysdeps/hppa/fpu/libm-test-ulps: Likewise.
+       * sysdeps/i386/fpu/libm-test-ulps: Likewise.
+       * sysdeps/ia64/fpu/libm-test-ulps: Likewise.
+       * sysdeps/m68k/fpu/libm-test-ulps: Likewise.
+       * sysdeps/mips/fpu/libm-test-ulps: Likewise.
+       * sysdeps/powerpc/fpu/libm-test-ulps: Likewise.
+       * sysdeps/s390/fpu/libm-test-ulps: Likewise.
+       * sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
+       * sysdeps/sh/sh4/fpu/libm-test-ulps: Likewise.
+       * sysdeps/sparc/sparc32/fpu/libm-test-ulps: Likewise.
+       * sysdeps/sparc/sparc64/fpu/libm-test-ulps: Likewise.
+
+--- libc/sysdeps/generic/s_cacosh.c    14 Dec 2005 10:12:27 -0000      1.1
++++ libc/sysdeps/generic/s_cacosh.c    15 Jan 2006 17:51:31 -0000      1.2
+@@ -73,6 +73,9 @@ __cacosh (__complex__ double x)
+       y = __csqrt (y);
++      if (__real__ x < 0.0)
++      y = -y;
++
+       __real__ y += __real__ x;
+       __imag__ y += __imag__ x;
+--- libc/sysdeps/generic/s_cacoshf.c   14 Dec 2005 10:12:45 -0000      1.1
++++ libc/sysdeps/generic/s_cacoshf.c   15 Jan 2006 17:51:31 -0000      1.2
+@@ -75,6 +75,9 @@ __cacoshf (__complex__ float x)
+       y = __csqrtf (y);
++      if (__real__ x < 0.0)
++      y = -y;
++
+       __real__ y += __real__ x;
+       __imag__ y += __imag__ x;
+--- libc/sysdeps/generic/s_cacoshl.c   14 Dec 2005 10:13:05 -0000      1.1
++++ libc/sysdeps/generic/s_cacoshl.c   15 Jan 2006 17:51:31 -0000      1.2
+@@ -73,6 +73,9 @@ __cacoshl (__complex__ long double x)
+       y = __csqrtl (y);
++      if (__real__ x < 0.0)
++      y = -y;
++
+       __real__ y += __real__ x;
+       __imag__ y += __imag__ x;
+--- libc/sysdeps/alpha/fpu/libm-test-ulps      17 Dec 2004 06:49:58 -0000      1.13
++++ libc/sysdeps/alpha/fpu/libm-test-ulps      15 Jan 2006 17:59:37 -0000      1.14
+@@ -20,12 +20,12 @@ float: 1
+ ifloat: 1
+ # cacosh
+-Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 7
+ idouble: 1
+ ifloat: 7
+-Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 3
+ idouble: 1
+--- libc/sysdeps/s390/fpu/libm-test-ulps       20 Jul 2005 18:18:56 -0000      1.13
++++ libc/sysdeps/s390/fpu/libm-test-ulps       15 Jan 2006 17:59:37 -0000      1.14
+@@ -17,12 +17,12 @@ float: 1
+ ifloat: 1
+ # cacosh
+-Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 7
+ idouble: 1
+ ifloat: 7
+-Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 3
+ idouble: 1
+--- libc/sysdeps/powerpc/fpu/libm-test-ulps    22 Dec 2005 00:56:05 -0000      1.15
++++ libc/sysdeps/powerpc/fpu/libm-test-ulps    15 Jan 2006 17:59:37 -0000      1.16
+@@ -17,12 +17,12 @@ float: 1
+ ifloat: 1
+ # cacosh
+-Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 7
+ idouble: 1
+ ifloat: 7
+-Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 3
+ idouble: 1
+--- libc/sysdeps/sparc/sparc32/fpu/libm-test-ulps      14 Jan 2006 12:09:02 -0000      1.13
++++ libc/sysdeps/sparc/sparc32/fpu/libm-test-ulps      15 Jan 2006 17:59:38 -0000      1.14
+@@ -33,10 +33,10 @@ ildouble: 1
+ # cacosh
+-Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 7
+ idouble: 1
+ ifloat: 7
+-Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 3
+--- libc/sysdeps/sparc/sparc64/fpu/libm-test-ulps      17 Dec 2004 07:40:44 -0000      1.16
++++ libc/sysdeps/sparc/sparc64/fpu/libm-test-ulps      15 Jan 2006 17:59:38 -0000      1.17
+@@ -33,14 +33,14 @@ ildouble: 1
+ ldouble: 1
+ # cacosh
+-Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 7
+ idouble: 1
+ ifloat: 7
+ ildouble: 5
+ ldouble: 5
+-Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 3
+ idouble: 1
+--- libc/sysdeps/mips/fpu/libm-test-ulps       23 Mar 2003 00:52:10 -0000      1.7
++++ libc/sysdeps/mips/fpu/libm-test-ulps       15 Jan 2006 17:59:37 -0000      1.8
+@@ -17,12 +17,12 @@ float: 1
+ ifloat: 1
+ # cacosh
+-Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 7
+ idouble: 1
+ ifloat: 7
+-Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 3
+ idouble: 1
+--- libc/sysdeps/sh/sh4/fpu/libm-test-ulps     23 Mar 2003 00:52:10 -0000      1.5
++++ libc/sysdeps/sh/sh4/fpu/libm-test-ulps     15 Jan 2006 17:59:38 -0000      1.6
+@@ -60,12 +60,12 @@ float: 1
+ ifloat: 1
+ # cacosh
+-Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 7
+ idouble: 1
+ ifloat: 7
+-Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 3
+ idouble: 1
+--- libc/sysdeps/i386/fpu/libm-test-ulps       30 Sep 2005 15:45:00 -0000      1.43
++++ libc/sysdeps/i386/fpu/libm-test-ulps       15 Jan 2006 17:59:37 -0000      1.44
+@@ -35,14 +35,14 @@ ildouble: 2
+ ldouble: 2
+ # cacosh
+-Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 9
+ idouble: 1
+ ifloat: 9
+ ildouble: 6
+ ldouble: 6
+-Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 4
+ idouble: 1
+--- libc/sysdeps/m68k/fpu/libm-test-ulps       24 Jun 2003 11:06:57 -0000      1.13
++++ libc/sysdeps/m68k/fpu/libm-test-ulps       15 Jan 2006 17:59:37 -0000      1.14
+@@ -36,14 +36,14 @@ ildouble: 2
+ ldouble: 2
+ # cacosh
+-Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 7
+ idouble: 1
+ ifloat: 7
+ ildouble: 6
+ ldouble: 6
+-Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ idouble: 1
+ ildouble: 2
+--- libc/sysdeps/ia64/fpu/libm-test-ulps       20 Dec 2005 15:17:24 -0000      1.18
++++ libc/sysdeps/ia64/fpu/libm-test-ulps       15 Jan 2006 17:59:37 -0000      1.19
+@@ -8,14 +8,14 @@ ildouble: 2
+ ldouble: 2
+ # cacosh
+-Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 7
+ idouble: 1
+ ifloat: 7
+ ildouble: 7
+ ldouble: 7
+-Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ idouble: 1
+ ildouble: 1
+--- libc/sysdeps/hppa/fpu/libm-test-ulps       23 Mar 2003 00:52:10 -0000      1.2
++++ libc/sysdeps/hppa/fpu/libm-test-ulps       15 Jan 2006 17:59:37 -0000      1.3
+@@ -17,12 +17,12 @@ float: 1
+ ifloat: 1
+ # cacosh
+-Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 7
+ idouble: 1
+ ifloat: 7
+-Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 3
+ idouble: 1
+--- libc/sysdeps/x86_64/fpu/libm-test-ulps     20 Jul 2005 18:15:21 -0000      1.10
++++ libc/sysdeps/x86_64/fpu/libm-test-ulps     15 Jan 2006 17:59:37 -0000      1.11
+@@ -48,14 +48,14 @@ ildouble: 2
+ ldouble: 2
+ # cacosh
+-Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 7
+ idouble: 1
+ ifloat: 7
+ ildouble: 6
+ ldouble: 6
+-Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
++Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+ double: 1
+ float: 3
+ idouble: 1
+--- libc/math/libm-test.inc    13 Oct 2005 19:07:12 -0000      1.66
++++ libc/math/libm-test.inc    15 Jan 2006 17:51:31 -0000      1.67
+@@ -1116,7 +1116,7 @@ cacosh_test (void)
+   TEST_c_c (cacosh, nan_value, nan_value, nan_value, nan_value);
+   TEST_c_c (cacosh, 0.75L, 1.25L, 1.13239363160530819522266333696834467L, 1.11752014915610270578240049553777969L);
+-  TEST_c_c (cacosh, -2, -3, -1.9833870299165354323470769028940395L, 2.1414491111159960199416055713254211L);
++  TEST_c_c (cacosh, -2, -3, 1.9833870299165354323470769028940395L, -2.1414491111159960199416055713254211L);
+   END (cacosh, complex);
+ }
diff --git a/src/patches/glibc/glibc-bz2173.patch b/src/patches/glibc/glibc-bz2173.patch
new file mode 100644 (file)
index 0000000..43bcee9
--- /dev/null
@@ -0,0 +1,150 @@
+2006-01-18  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2173]
+       * libio/fileops.c (_IO_new_file_fopen): If ,ccs= is given, also
+       set vtable to the wide vtable.
+       * libio/tst-fopenloc2.c: New file.
+       * libio/Makefile (tests): Add tst-fopenloc2.
+
+--- libc/libio/Makefile        16 Jan 2006 20:10:26 -0000      1.84
++++ libc/libio/Makefile        19 Jan 2006 01:22:48 -0000      1.85
+@@ -54,7 +54,7 @@ tests = tst_swprintf tst_wprintf tst_sws
+       tst-freopen bug-rewind bug-rewind2 bug-ungetc bug-fseek \
+       tst-mmap-eofsync tst-mmap-fflushsync bug-mmap-fflush \
+       tst-mmap2-eofsync tst-mmap-offend bug-fopena+ bug-wfflush \
+-      bug-ungetc2 bug-ftell bug-ungetc3 bug-ungetc4
++      bug-ungetc2 bug-ftell bug-ungetc3 bug-ungetc4 tst-fopenloc2
+ test-srcs = test-freopen
+ all: # Make this the default target; it will be defined in Rules.
+--- libc/libio/fileops.c       27 Sep 2005 18:49:43 -0000      1.109
++++ libc/libio/fileops.c       19 Jan 2006 00:38:35 -0000      1.110
+@@ -399,6 +399,9 @@ _IO_new_file_fopen (fp, filename, mode, 
+         /* And now the transliteration.  */
+         cc->__cd_out.__cd.__data[0].__trans = &__libio_translit;
++        /* From now on use the wide character callback functions.  */
++        ((struct _IO_FILE_plus *) fp)->vtable = fp->_wide_data->_wide_vtable;
++
+         /* Set the mode now.  */
+         result->_mode = 1;
+       }
+--- libc/libio/tst-fopenloc2.c 1 Jan 1970 00:00:00 -0000
++++ libc/libio/tst-fopenloc2.c 19 Jan 2006 01:22:20 -0000      1.1
+@@ -0,0 +1,116 @@
++#include <errno.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <wchar.h>
++
++
++static const struct
++{
++  const char *enc;
++  const char *data;
++  size_t datalen;
++  const wchar_t *expected;
++  size_t expectedlen;
++} tests[] =
++  {
++    { "UCS-4LE", "a\0\0\0b\0\0\0", 8, L"ab", 2 },
++    { "UCS-4BE", "\0\0\0a\0\0\0b", 8, L"ab", 2 },
++  };
++#define ntests (sizeof (tests) / sizeof (tests[0]))
++
++
++static int do_test (void);
++#define TEST_FUNCTION do_test ()
++
++static void prepare (void);
++#define PREPARE(argc, argv) prepare ();
++
++#include "../test-skeleton.c"
++
++
++static int fd;
++static char *tmpname;
++
++
++static void
++prepare (void)
++{
++  fd = create_temp_file ("tst-fopenloc2", &tmpname);
++  if (fd == -1)
++    {
++      puts ("cannot open temp file");
++      exit (1);
++    }
++}
++
++
++static int
++do_test (void)
++{
++  for (int i = 0; i < ntests; ++i)
++    {
++      if (ftruncate (fd, 0) != 0)
++      {
++        printf ("ftruncate in round %d failed\n", i + 1);
++        return 1;
++      }
++
++      if (TEMP_FAILURE_RETRY (write (fd, tests[i].data, tests[i].datalen))
++        != tests[i].datalen)
++      {
++        printf ("write in round %d failed\n", i + 1);
++        return 1;
++      }
++
++      if (lseek (fd, 0, SEEK_SET) != 0)
++      {
++        printf ("lseek in round %d failed\n", i + 1);
++        return 1;
++      }
++
++      char *ccs;
++      if (asprintf (&ccs, "r,ccs=%s", tests[i].enc) == -1)
++      {
++        printf ("asprintf in round %d failed\n", i + 1);
++        return 1;
++      }
++
++      FILE *fp = fopen (tmpname, ccs);
++      if (fp == NULL)
++      {
++        printf ("fopen in round %d failed\n", i + 1);
++        return 1;
++      }
++
++#define LINELEN 100
++      wchar_t line[LINELEN];
++      if (fgetws (line, LINELEN, fp) != line)
++      {
++        printf ("fgetws in round %d failed\n", i + 1);
++        return 1;
++      }
++
++      if (wcslen (line) != tests[i].expectedlen)
++      {
++        printf ("round %d: expected length %zu, got length %zu\n",
++                i + 1, tests[i].expectedlen, wcslen (line));
++        return 1;
++      }
++
++      if (wcscmp (tests[i].expected, line) != 0)
++      {
++        printf ("round %d: expected L\"%ls\", got L\"%ls\"\n",
++                i + 1, tests[i].expected, line);
++        return 1;
++      }
++
++      fclose (fp);
++
++      free (ccs);
++    }
++
++  close (fd);
++
++  return 0;
++}
diff --git a/src/patches/glibc/glibc-bz2182.patch b/src/patches/glibc/glibc-bz2182.patch
new file mode 100644 (file)
index 0000000..ed13424
--- /dev/null
@@ -0,0 +1,46 @@
+2006-08-03  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2182]
+       * sysdeps/generic/s_cacosh.c: Return values from positive branch.
+       * sysdeps/generic/s_cacoshf.c: Likewise.
+       * sysdeps/generic/s_cacoshl.c: Likewise.
+
+--- libc/sysdeps/generic/s_cacosh.c    15 Jan 2006 17:51:31 -0000      1.2
++++ libc/sysdeps/generic/s_cacosh.c    3 Aug 2006 20:35:41 -0000       1.3
+@@ -80,6 +80,10 @@ __cacosh (__complex__ double x)
+       __imag__ y += __imag__ x;
+       res = __clog (y);
++
++      /* We have to use the positive branch.  */
++      if (__real__ res < 0.0)
++      res = -res;
+     }
+   return res;
+--- libc/sysdeps/generic/s_cacoshf.c   15 Jan 2006 17:51:31 -0000      1.2
++++ libc/sysdeps/generic/s_cacoshf.c   3 Aug 2006 20:35:41 -0000       1.3
+@@ -95,6 +95,10 @@ __cacoshf (__complex__ float x)
+                                          + ro);
+       __imag__ res = __ieee754_atan2f (__imag__ x + b, __real__ x + a);
+ #endif
++
++      /* We have to use the positive branch.  */
++      if (__real__ res < 0.0)
++      res = -res;
+     }
+   return res;
+--- libc/sysdeps/generic/s_cacoshl.c   15 Jan 2006 17:51:31 -0000      1.2
++++ libc/sysdeps/generic/s_cacoshl.c   3 Aug 2006 20:35:41 -0000       1.3
+@@ -80,6 +80,10 @@ __cacoshl (__complex__ long double x)
+       __imag__ y += __imag__ x;
+       res = __clogl (y);
++
++      /* We have to use the positive branch.  */
++      if (__real__ res < 0.0)
++      res = -res;
+     }
+   return res;
diff --git a/src/patches/glibc/glibc-bz2226.patch b/src/patches/glibc/glibc-bz2226.patch
new file mode 100644 (file)
index 0000000..189bdf2
--- /dev/null
@@ -0,0 +1,17 @@
+2006-02-12  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2226]
+       * libio/wgenops.c (_IO_wsetb): Use correct size of wide char
+       buffer in FREE_BUF call.
+
+--- libc/libio/wgenops.c       14 Sep 2004 04:24:45 -0000      1.13
++++ libc/libio/wgenops.c       12 Feb 2006 21:20:57 -0000      1.14
+@@ -116,7 +116,7 @@ _IO_wsetb (f, b, eb, a)
+      int a;
+ {
+   if (f->_wide_data->_IO_buf_base && !(f->_flags & _IO_USER_BUF))
+-    FREE_BUF (f->_wide_data->_IO_buf_base, _IO_wblen (f));
++    FREE_BUF (f->_wide_data->_IO_buf_base, _IO_wblen (f) * sizeof (wchar_t));
+   f->_wide_data->_IO_buf_base = b;
+   f->_wide_data->_IO_buf_end = eb;
+   if (a)
diff --git a/src/patches/glibc/glibc-bz2268.patch b/src/patches/glibc/glibc-bz2268.patch
new file mode 100644 (file)
index 0000000..d0df514
--- /dev/null
@@ -0,0 +1,25 @@
+2006-02-03  Roland McGrath  <roland@redhat.com>
+
+       [BZ #2268]
+       * sysdeps/posix/profil.c (__profil): Use __profile_frequency to choose
+       timer interval, don't assume smallest possible interval is it.
+
+--- libc/sysdeps/posix/profil.c        15 Dec 2005 21:10:10 -0000      1.13
++++ libc/sysdeps/posix/profil.c        3 Feb 2006 22:28:31 -0000       1.14
+@@ -22,6 +23,7 @@
+ #include <errno.h>
+ #include <signal.h>
+ #include <sys/time.h>
++#include <libc-internal.h>
+ #ifndef SIGPROF
+@@ -110,7 +112,7 @@ __profil (u_short *sample_buffer, size_t
+     return -1;
+   timer.it_value.tv_sec = 0;
+-  timer.it_value.tv_usec = 1;
++  timer.it_value.tv_usec = 1000000 / __profile_frequency ();
+   timer.it_interval = timer.it_value;
+   return __setitimer (ITIMER_PROF, &timer, otimer_ptr);
+ }
diff --git a/src/patches/glibc/glibc-bz2415.patch b/src/patches/glibc/glibc-bz2415.patch
new file mode 100644 (file)
index 0000000..6d5e087
--- /dev/null
@@ -0,0 +1,22 @@
+2006-04-01  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2415]
+       * elf/ldd.bash.in: Create better error messages for invalid input
+       files.
+
+--- libc/elf/ldd.bash.in       1 Jan 2006 19:15:56 -0000       1.35
++++ libc/elf/ldd.bash.in       1 Apr 2006 20:16:17 -0000       1.36
+@@ -144,9 +144,12 @@ for file do
+   *) file=./$file
+      ;;
+   esac
+-  if test ! -f "$file"; then
++  if test ! -e "$file"; then
+     echo "ldd: ${file}:" $"No such file or directory" >&2
+     result=1
++  elif test ! -f "$file"; then
++    echo "ldd: ${file}:" $"not regular file" >&2
++    result=1
+   elif test -r "$file"; then
+     test -x "$file" || echo 'ldd:' $"\
+ warning: you do not have execution permission for" "\`$file'" >&2
diff --git a/src/patches/glibc/glibc-bz2418.patch b/src/patches/glibc/glibc-bz2418.patch
new file mode 100644 (file)
index 0000000..d1a3746
--- /dev/null
@@ -0,0 +1,25 @@
+2006-04-02  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2418]
+       * sysdeps/unix/sysv/linux/getcwd.c (__getcwd): Use larger of PATH_MAX
+       and page size when allocating buffer.
+
+--- libc/sysdeps/unix/sysv/linux/getcwd.c      8 Jan 2006 08:21:15 -0000       1.23
++++ libc/sysdeps/unix/sysv/linux/getcwd.c      2 Apr 2006 17:58:28 -0000       1.24
+@@ -27,6 +27,7 @@
+ #include <sysdep.h>
+ #include <sys/syscall.h>
+ #include <bp-checks.h>
++#include <sys/param.h>
+ #include "kernel-features.h"
+@@ -86,7 +87,7 @@ __getcwd (char *buf, size_t size)
+         return NULL;
+       }
+-      alloc_size = PATH_MAX;
++      alloc_size = MAX (PATH_MAX, __getpagesize ());
+     }
+   if (buf == NULL)
diff --git a/src/patches/glibc/glibc-bz2420.patch b/src/patches/glibc/glibc-bz2420.patch
new file mode 100644 (file)
index 0000000..3a40753
--- /dev/null
@@ -0,0 +1,131 @@
+2006-04-25  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2420]
+       * stdlib/strfmon_l.c (__vstrfmon_l): Fix handling of ! modifier.
+       * localedata/Makefile: Add rules to build and run tst-strfmon1.
+       * localedata/tst-strfmon1.c: New file.
+
+--- libc/stdlib/strfmon_l.c    14 Jan 2006 12:08:37 -0000      1.6
++++ libc/stdlib/strfmon_l.c    26 Apr 2006 05:14:49 -0000      1.7
+@@ -486,23 +486,21 @@ __vstrfmon_l (char *s, size_t maxsize, _
+           }
+         if (print_curr_symbol)
+-          {
+-            out_string (currency_symbol);
++          out_string (currency_symbol);
+-            if (sign_posn == 4)
+-              {
+-                if (sep_by_space == 2)
+-                  out_char (space_char);
+-                out_string (sign_string);
+-                if (sep_by_space == 1)
+-                  /* POSIX.2 and SUS are not clear on this case, but C99
+-                     says a space follows the adjacent-symbol-and-sign */
+-                  out_char (' ');
+-              }
+-            else
+-              if (sep_by_space == 1)
+-                out_char (space_char);
++        if (sign_posn == 4)
++          {
++            if (print_curr_symbol && sep_by_space == 2)
++              out_char (space_char);
++            out_string (sign_string);
++            if (sep_by_space == 1)
++              /* POSIX.2 and SUS are not clear on this case, but C99
++                 says a space follows the adjacent-symbol-and-sign */
++              out_char (' ');
+           }
++        else
++          if (print_curr_symbol && sep_by_space == 1)
++            out_char (space_char);
+       }
+       else
+       if (sign_posn != 0 && sign_posn != 2 && sign_posn != 3
+@@ -561,12 +559,13 @@ __vstrfmon_l (char *s, size_t maxsize, _
+                 || (sign_posn == 0 && sep_by_space == 1))
+               out_char (space_char);
+             out_nstring (currency_symbol, currency_symbol_len);
+-            if (sign_posn == 4)
+-              {
+-                if (sep_by_space == 2)
+-                  out_char (' ');
+-                out_string (sign_string);
+-              }
++          }
++          
++        if (sign_posn == 4)
++          {
++            if (sep_by_space == 2)
++              out_char (' ');
++            out_string (sign_string);
+           }
+       }
+--- libc/localedata/Makefile   25 Sep 2005 17:01:12 -0000      1.102
++++ libc/localedata/Makefile   26 Apr 2006 05:14:03 -0000      1.103
+@@ -92,7 +92,8 @@ locale_test_suite := tst_iswalnum tst_is
+                    tst_wctype tst_wcwidth
+ tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
+-      tst-leaks tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale
++      tst-leaks tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \
++      tst-strfmon1
+ ifeq (yes,$(build-shared))
+ ifneq (no,$(PERL))
+ tests: $(objpfx)mtrace-tst-leaks
+@@ -282,6 +283,7 @@ tst-digits-ENV = $(TEST_MBWC_ENV)
+ tst-mbswcs6-ENV = $(TEST_MBWC_ENV)
+ tst-xlocale1-ENV = $(TEST_MBWC_ENV)
+ tst-xlocale2-ENV = $(TEST_MBWC_ENV)
++tst-strfmon1-ENV = $(TEST_MBWC_ENV)
+ tst-setlocale-ENV = LOCPATH=$(common-objpfx)localedata LC_ALL=ja_JP.EUC-JP
+--- libc/localedata/tst-strfmon1.c     1 Jan 1970 00:00:00 -0000
++++ libc/localedata/tst-strfmon1.c     26 Apr 2006 05:13:06 -0000      1.1
+@@ -0,0 +1,42 @@
++#include <monetary.h>
++#include <locale.h>
++#include <stdio.h>
++#include <string.h>
++
++static const struct
++{
++  const char *locale;
++  const char *expected;
++} tests[] =
++  {
++    { "de_DE.ISO-8859-1", "|-12,34 EUR|-12,34|" },
++    { "da_DK.ISO-8859-1", "|kr -12,34|-12,34|" },
++    { "zh_TW.EUC-TW", "|-NT$12.34|-12.34|" },
++    { "sv_SE.ISO-8859-1", "|-12,34 kr|-12,34|" }
++  };
++#define ntests (sizeof (tests) / sizeof (tests[0]))
++
++
++static int
++do_test (void)
++{
++  int res = 0;
++  for (int i = 0; i < ntests; ++i)
++    {
++      char buf[500];
++      if (setlocale (LC_ALL, tests[i].locale) == NULL)
++      {
++        printf ("failed to set locale %s\n", tests[i].locale);
++        res = 1;
++        continue;
++      }
++      strfmon (buf, sizeof (buf), "|%n|%!n|", -12.34, -12.34);
++      int fail = strcmp (buf, tests[i].expected) != 0;
++      printf ("%s%s\n", buf, fail ? " *** FAIL ***" : "");
++      res |= fail;
++    }
++  return res;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-bz2451.patch b/src/patches/glibc/glibc-bz2451.patch
new file mode 100644 (file)
index 0000000..9298e86
--- /dev/null
@@ -0,0 +1,147 @@
+2006-03-17  Roland McGrath  <roland@redhat.com>
+
+       * elf/tst-leaks1.c: Include <stdio.h>.
+
+2006-03-13  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #2451]
+       * elf/dl-load.c (open_verify): Add free_name argument, if true, free
+       name before calling lose.
+       (open_path): Adjust caller.
+       (_dl_map_object): Adjust callers.  Free name_copy before calling
+       _dl_signal_error.
+       * elf/Makefile: Add rules to build and run tst-leaks1.
+       * elf/tst-leaks1.c: New test.
+
+--- libc/elf/Makefile  1 Mar 2006 06:18:26 -0000       1.310
++++ libc/elf/Makefile  19 Mar 2006 07:47:47 -0000      1.312
+@@ -87,7 +87,8 @@ distribute   := rtld-Rules \
+                  unload3mod1.c unload3mod2.c unload3mod3.c unload3mod4.c \
+                  unload4mod1.c unload4mod2.c unload4mod3.c unload4mod4.c \
+                  unload6mod1.c unload6mod2.c unload6mod3.c \
+-                 order2mod1.c order2mod2.c order2mod3.c order2mod4.c
++                 order2mod1.c order2mod2.c order2mod3.c order2mod4.c \
++                 tst-leaks1.c
+ CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables
+ CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables
+@@ -135,7 +136,7 @@ vpath %.c ../locale/programs
+ endif
+ endif
+-tests = tst-tls1 tst-tls2 tst-tls9
++tests = tst-tls1 tst-tls2 tst-tls9 tst-leaks1
+ ifeq (yes,$(have-initfini-array))
+ tests += tst-array1 tst-array2 tst-array3 tst-array4
+ endif
+@@ -170,6 +171,7 @@ endif
+ ifeq (yesyes,$(have-fpie)$(build-shared))
+ tests: $(objpfx)tst-pie1.out
+ endif
++tests: $(objpfx)tst-leaks1-mem
+ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
+               testobj1_1 failobj constload2 constload3 unloadmod \
+               dep1 dep2 dep3 dep4 $(modules-vis-$(have-protected)) \
+@@ -828,3 +830,9 @@ $(objpfx)order2mod1.so: $(objpfx)order2m
+ $(objpfx)order2mod4.so: $(objpfx)order2mod3.so
+ $(objpfx)order2mod2.so: $(objpfx)order2mod3.so
+ order2mod2.so-no-z-defs = yes
++
++$(objpfx)tst-leaks1: $(libdl)
++$(objpfx)tst-leaks1-mem: $(objpfx)tst-leaks1.out
++      $(common-objpfx)malloc/mtrace $(objpfx)tst-leaks1.mtrace > $@
++
++tst-leaks1-ENV = MALLOC_TRACE=$(objpfx)tst-leaks1.mtrace
+--- libc/elf/dl-load.c 17 Oct 2005 20:59:28 -0000      1.273
++++ libc/elf/dl-load.c 15 Mar 2006 19:20:04 -0000      1.274
+@@ -1491,7 +1491,7 @@ print_search_path (struct r_search_path_
+    this could mean there is something wrong in the installation and the
+    user might want to know about this.  */
+ static int
+-open_verify (const char *name, struct filebuf *fbp)
++open_verify (const char *name, struct filebuf *fbp, bool free_name)
+ {
+   /* This is the expected ELF header.  */
+ #define ELF32_CLASS ELFCLASS32
+@@ -1551,6 +1551,12 @@ open_verify (const char *name, struct fi
+         errstring = (errval == 0
+                      ? N_("file too short") : N_("cannot read file data"));
+       call_lose:
++        if (free_name)
++          {
++            char *realname = (char *) name;
++            name = strdupa (realname);
++            free (realname);
++          }
+         lose (errval, fd, name, NULL, NULL, errstring);
+       }
+@@ -1728,7 +1734,7 @@ open_path (const char *name, size_t name
+         if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
+           _dl_debug_printf ("  trying file=%s\n", buf);
+-        fd = open_verify (buf, fbp);
++        fd = open_verify (buf, fbp, false);
+         if (this_dir->status[cnt] == unknown)
+           {
+             if (fd != -1)
+@@ -1965,7 +1971,7 @@ _dl_map_object (struct link_map *loader,
+             if (cached != NULL)
+               {
+-                fd = open_verify (cached, &fb);
++                fd = open_verify (cached, &fb, false);
+                 if (__builtin_expect (fd != -1, 1))
+                   {
+                     realname = local_strdup (cached);
+@@ -2001,7 +2007,7 @@ _dl_map_object (struct link_map *loader,
+       fd = -1;
+       else
+       {
+-        fd = open_verify (realname, &fb);
++        fd = open_verify (realname, &fb, true);
+         if (__builtin_expect (fd, 0) == -1)
+           free (realname);
+       }
+@@ -2028,8 +2034,11 @@ _dl_map_object (struct link_map *loader,
+         if ((name_copy = local_strdup (name)) == NULL
+             || (l = _dl_new_object (name_copy, name, type, loader,
+                                     mode, nsid)) == NULL)
+-          _dl_signal_error (ENOMEM, name, NULL,
+-                            N_("cannot create shared object descriptor"));
++          {
++            free (name_copy);
++            _dl_signal_error (ENOMEM, name, NULL,
++                              N_("cannot create shared object descriptor"));
++          }
+         /* Signal that this is a faked entry.  */
+         l->l_faked = 1;
+         /* Since the descriptor is initialized with zero we do not
+--- libc/elf/tst-leaks1.c      1 Jan 1970 00:00:00 -0000
++++ libc/elf/tst-leaks1.c      19 Mar 2006 07:47:56 -0000      1.2
+@@ -0,0 +1,25 @@
++#include <stdio.h>
++#include <dlfcn.h>
++#include <mcheck.h>
++#include <stdlib.h>
++
++int
++main (void)
++{
++  mtrace ();
++
++  int ret = 0;
++  for (int i = 0; i < 10; i++)
++    {
++      void *h = dlopen (i < 5 ? "./tst-leaks1.c"
++                            : "$ORIGIN/tst-leaks1.o", RTLD_LAZY);
++      if (h != NULL)
++      {
++        puts ("dlopen unexpectedly succeeded");
++        ret = 1;
++        dlclose (h);
++      }
++    }
++
++  return ret;
++}
diff --git a/src/patches/glibc/glibc-bz2498.patch b/src/patches/glibc/glibc-bz2498.patch
new file mode 100644 (file)
index 0000000..46f5471
--- /dev/null
@@ -0,0 +1,44 @@
+2006-04-01  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2498]
+       * nscd/connections.c (main_loop_poll): If the connection cannot be
+       accepted because of user-imposed limits close the descriptor.
+
+--- libc/nscd/connections.c    3 Jan 2006 21:26:28 -0000       1.82
++++ libc/nscd/connections.c    1 Apr 2006 18:49:53 -0000       1.83
+@@ -1556,18 +1556,24 @@ main_loop_poll (void)
+             /* We have a new incoming connection.  Accept the connection.  */
+             int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
+-            /* use the descriptor if we have not reached the limit.  */
+-            if (fd >= 0 && firstfree < nconns)
++            /* Use the descriptor if we have not reached the limit.  */
++            if (fd >= 0)
+               {
+-                conns[firstfree].fd = fd;
+-                conns[firstfree].events = POLLRDNORM;
+-                starttime[firstfree] = now;
+-                if (firstfree >= nused)
+-                  nused = firstfree + 1;
+-
+-                do
+-                  ++firstfree;
+-                while (firstfree < nused && conns[firstfree].fd != -1);
++                if (firstfree < nconns)
++                  {
++                    conns[firstfree].fd = fd;
++                    conns[firstfree].events = POLLRDNORM;
++                    starttime[firstfree] = now;
++                    if (firstfree >= nused)
++                      nused = firstfree + 1;
++
++                    do
++                      ++firstfree;
++                    while (firstfree < nused && conns[firstfree].fd != -1);
++                  }
++                else
++                  /* We cannot use the connection so close it.  */
++                  close (fd);
+               }
+             --n;
diff --git a/src/patches/glibc/glibc-bz2499.patch b/src/patches/glibc/glibc-bz2499.patch
new file mode 100644 (file)
index 0000000..73b6cad
--- /dev/null
@@ -0,0 +1,97 @@
+2006-05-06  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2499]
+       * resolv/nss_dns/dns-canon.c (_nss_dns_getcanonname_r): Avoid
+       possibly unaligned memory accesses.
+
+       * resolv/res_mkquery.c: Correct buffer overflow check for
+       NS_NOTIFY_OP.
+
+       * resolv/res_send.c (send_dg): Rewrite error handling to be
+       more compact and avoid double recomputation of timeouts.
+       Pass MSG_NOSIGNAL to send.
+
+       [BZ #2499]
+       * resolv/res_query.c (__libc_res_nquery): If answerp != NULL,
+       __libc_res_nsend might reallocate the buffer for the answer.  In
+       this case we have to reload the HP pointer.
+
+--- libc/resolv/res_mkquery.c  27 Oct 2004 21:27:29 -0000      1.15
++++ libc/resolv/res_mkquery.c  6 May 2006 18:04:12 -0000       1.16
+@@ -155,10 +155,14 @@ res_nmkquery(res_state statp,
+        * perform opcode specific processing
+        */
+       switch (op) {
+-      case QUERY:     /*FALLTHROUGH*/
+       case NS_NOTIFY_OP:
++              if ((buflen -= QFIXEDSZ + (data == NULL ? 0 : RRFIXEDSZ)) < 0)
++                      return (-1);
++              goto compose;
++      case QUERY:     /*FALLTHROUGH*/
+               if ((buflen -= QFIXEDSZ) < 0)
+                       return (-1);
++      compose:
+               if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
+                       return (-1);
+               cp += n;
+@@ -173,7 +177,6 @@ res_nmkquery(res_state statp,
+               /*
+                * Make an additional record for completion domain.
+                */
+-              buflen -= RRFIXEDSZ;
+               n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr);
+               if (n < 0)
+                       return (-1);
+--- libc/resolv/res_query.c    18 Oct 2004 05:09:59 -0000      1.23
++++ libc/resolv/res_query.c    6 May 2006 07:15:53 -0000       1.24
+@@ -163,6 +165,10 @@ __libc_res_nquery(res_state statp,
+               return (n);
+       }
++      if (answerp != NULL)
++        /* __libc_res_nsend might have reallocated the buffer.  */
++        hp = (HEADER *) *answerp;
++
+       if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
+ #ifdef DEBUG
+               if (statp->options & RES_DEBUG)
+--- libc/resolv/res_send.c     1 Nov 2005 00:07:49 -0000       1.45
++++ libc/resolv/res_send.c     6 May 2006 17:35:50 -0000       1.49
+@@ -914,7 +914,7 @@ send_dg(res_state statp,
+       }
+       __set_errno (0);
+       if (pfd[0].revents & POLLOUT) {
+-              if (send(pfd[0].fd, (char*)buf, buflen, 0) != buflen) {
++              if (send(pfd[0].fd, (char*)buf, buflen, MSG_NOSIGNAL) != buflen) {
+                       if (errno == EINTR || errno == EAGAIN)
+                               goto recompute_resend;
+                       Perror(statp, stderr, "send", errno);
+--- libc/resolv/nss_dns/dns-canon.c    19 Aug 2004 18:56:11 -0000      1.3
++++ libc/resolv/nss_dns/dns-canon.c    6 May 2006 19:17:41 -0000       1.4
+@@ -101,7 +103,7 @@ _nss_dns_getcanonname_r (const char *nam
+             ptr += s;
+             /* Check whether type and class match.  */
+-            unsigned int type = ntohs (*(uint16_t *) ptr);
++            unsigned int type = ns_get16 (ptr);
+             if (type == qtypes[i])
+               {
+                 /* We found the record.  */
+@@ -130,15 +133,15 @@ _nss_dns_getcanonname_r (const char *nam
+             if (type != ns_t_cname)
+               goto unavail;
+             ptr += sizeof (uint16_t);
+-            if (*(uint16_t *) ptr != htons (ns_c_in))
++            if (ns_get16 (ptr) != ns_c_in)
+               goto unavail;
+             /* Also skip over the TTL.  */
+             ptr += sizeof (uint16_t) + sizeof (uint32_t);
+             /* Skip over the data length and data.  */
+-            ptr += sizeof (uint16_t) + ntohs (*(uint16_t *) ptr);
++            ptr += sizeof (uint16_t) + ns_get16 (ptr);
+           }
+       }
+     }
diff --git a/src/patches/glibc/glibc-bz2501.patch b/src/patches/glibc/glibc-bz2501.patch
new file mode 100644 (file)
index 0000000..e7ce692
--- /dev/null
@@ -0,0 +1,76 @@
+2006-04-02  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2501]
+       * nscd/nscd_helper.c (get_mapping): Rewrite code to send request
+       so it uses send and not writev.
+
+--- libc/nscd/nscd_helper.c    1 Mar 2006 05:39:03 -0000       1.14
++++ libc/nscd/nscd_helper.c    2 Apr 2006 18:22:23 -0000       1.15
+@@ -175,35 +175,40 @@ get_mapping (request_type type, const ch
+   struct mapped_database *result = NO_MAPPING;
+ #ifdef SCM_RIGHTS
+   const size_t keylen = strlen (key) + 1;
+-  char resdata[keylen];
+   int saved_errno = errno;
+   int mapfd = -1;
+   /* Send the request.  */
+-  struct iovec iov[2];
+-  request_header req;
++  struct
++  {
++    request_header req;
++    char key[keylen];
++  } reqdata;
+   int sock = open_socket ();
+   if (sock < 0)
+     goto out;
+-  req.version = NSCD_VERSION;
+-  req.type = type;
+-  req.key_len = keylen;
+-
+-  iov[0].iov_base = &req;
+-  iov[0].iov_len = sizeof (req);
+-  iov[1].iov_base = (void *) key;
+-  iov[1].iov_len = keylen;
+-
+-  if (__builtin_expect (TEMP_FAILURE_RETRY (__writev (sock, iov, 2))
+-                      != iov[0].iov_len + iov[1].iov_len, 0))
++  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;
+@@ -230,11 +235,7 @@ get_mapping (request_type type, const ch
+   if (wait_on_socket (sock) <= 0)
+     goto out_close2;
+-#ifndef MSG_NOSIGNAL
+-# define MSG_NOSIGNAL 0
+-#endif
+-  if (__builtin_expect (TEMP_FAILURE_RETRY (__recvmsg (sock, &msg,
+-                                                     MSG_NOSIGNAL))
++  if (__builtin_expect (TEMP_FAILURE_RETRY (__recvmsg (sock, &msg, 0))
+                       != keylen, 0))
+     goto out_close2;
diff --git a/src/patches/glibc/glibc-bz2502.patch b/src/patches/glibc/glibc-bz2502.patch
new file mode 100644 (file)
index 0000000..b84711d
--- /dev/null
@@ -0,0 +1,17 @@
+2006-05-01  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2502]
+       * iconvdata/utf-7.c: Don't require more than one character after
+       the '+' sign starting Unicode shifted sequences.
+
+--- libc/iconvdata/utf-7.c     26 Mar 2004 06:41:46 -0000      1.6
++++ libc/iconvdata/utf-7.c     2 May 2006 05:17:29 -0000       1.7
+@@ -170,7 +170,7 @@ base64 (unsigned int i)
+         }                                                                   \
+       else if (__builtin_expect (ch == '+', 1))                             \
+         {                                                                   \
+-          if (__builtin_expect (inptr + 2 >= inend, 0))                     \
++          if (__builtin_expect (inptr + 2 > inend, 0))                      \
+             {                                                               \
+               /* Not enough input available.  */                            \
+               result = __GCONV_INCOMPLETE_INPUT;                            \
diff --git a/src/patches/glibc/glibc-bz2509.patch b/src/patches/glibc/glibc-bz2509.patch
new file mode 100644 (file)
index 0000000..d8051d4
--- /dev/null
@@ -0,0 +1,89 @@
+2006-05-05  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #2509]
+       * stdio-common/tst-printf.sh: Adjust for tst-printf.c change even
+       on 32-bit arches.
+
+2006-05-02  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2509]
+       * stdio-common/vfprintf.c (process_arg): Fix reading of signed
+       short and byte values from parameter list.
+       * stdio-common/tst-printf.c (main): Add more tests.
+       * stdio-common/tst-printf.sh: Adjust for tst-printf.c change.
+
+--- libc/stdio-common/vfprintf.c       14 Jan 2006 12:09:45 -0000      1.133
++++ libc/stdio-common/vfprintf.c       2 May 2006 20:25:15 -0000       1.134
+@@ -530,14 +530,24 @@ vfprintf (FILE *s, const CHAR_T *format,
+           {                                                                 \
+             if (is_long_num)                                                \
+               signed_number = va_arg (ap, long int);                        \
+-            else  /* `char' and `short int' will be promoted to `int'.  */  \
++            else if (is_char)                                               \
++              signed_number = (signed char) va_arg (ap, unsigned int);      \
++            else if (!is_short)                                             \
+               signed_number = va_arg (ap, int);                             \
++            else                                                            \
++              signed_number = (short int) va_arg (ap, unsigned int);        \
+           }                                                                 \
+         else                                                                \
+           if (is_long_num)                                                  \
+             signed_number = args_value[fspec->data_arg].pa_long_int;        \
+-          else  /* `char' and `short int' will be promoted to `int'.  */    \
++          else if (is_char)                                                 \
++            signed_number = (signed char)                                   \
++              args_value[fspec->data_arg].pa_u_int;                         \
++          else if (!is_short)                                               \
+             signed_number = args_value[fspec->data_arg].pa_int;             \
++          else                                                              \
++            signed_number = (short int)                                     \
++              args_value[fspec->data_arg].pa_u_int;                         \
+                                                                             \
+         is_negative = signed_number < 0;                                    \
+         number.word = is_negative ? (- signed_number) : signed_number;      \
+--- libc/stdio-common/tst-printf.c     15 Mar 2002 22:05:52 -0000      1.16
++++ libc/stdio-common/tst-printf.c     2 May 2006 20:23:30 -0000       1.17
+@@ -273,6 +273,15 @@ I am ready for my first lesson today.";
+   printf ("printf (\"%%hhu\", %u) = %hhu\n", UCHAR_MAX + 2, UCHAR_MAX + 2);
+   printf ("printf (\"%%hu\", %u) = %hu\n", USHRT_MAX + 2, USHRT_MAX + 2);
++  printf ("printf (\"%%hhi\", %i) = %hhi\n", UCHAR_MAX + 2, UCHAR_MAX + 2);
++  printf ("printf (\"%%hi\", %i) = %hi\n", USHRT_MAX + 2, USHRT_MAX + 2);
++
++  printf ("printf (\"%%1$hhu\", %2$u) = %1$hhu\n",
++        UCHAR_MAX + 2, UCHAR_MAX + 2);
++  printf ("printf (\"%%1$hu\", %2$u) = %1$hu\n", USHRT_MAX + 2, USHRT_MAX + 2);
++  printf ("printf (\"%%1$hhi\", %2$i) = %1$hhi\n",
++        UCHAR_MAX + 2, UCHAR_MAX + 2);
++  printf ("printf (\"%%1$hi\", %2$i) = %1$hi\n", USHRT_MAX + 2, USHRT_MAX + 2);
+   puts ("--- Should be no further output. ---");
+   rfg1 ();
+--- libc/stdio-common/tst-printf.sh    15 Mar 2002 22:06:24 -0000      1.8
++++ libc/stdio-common/tst-printf.sh    2 May 2006 20:23:51 -0000       1.10
+@@ -136,6 +136,12 @@ Test ok.
+ sprintf (buf, "%07Lo", 040000000000ll) = 40000000000
+ printf ("%hhu", 257) = 1
+ printf ("%hu", 65537) = 1
++printf ("%hhi", 257) = 1
++printf ("%hi", 65537) = 1
++printf ("%1$hhu", 257) = 1
++printf ("%1$hu", 65537) = 1
++printf ("%1$hhi", 257) = 1
++printf ("%1$hi", 65537) = 1
+ --- Should be no further output. ---
+ EOF
+ cmp - ${common_objpfx}stdio-common/tst-printf.out > /dev/null 2>&1 ||
+@@ -246,6 +246,12 @@ Test ok.
+ sprintf (buf, "%07Lo", 040000000000ll) = 40000000000
+ printf ("%hhu", 257) = 1
+ printf ("%hu", 65537) = 1
++printf ("%hhi", 257) = 1
++printf ("%hi", 65537) = 1
++printf ("%1$hhu", 257) = 1
++printf ("%1$hu", 65537) = 1
++printf ("%1$hhi", 257) = 1
++printf ("%1$hi", 65537) = 1
+ --- Should be no further output. ---
+ EOF
+ cmp - ${common_objpfx}stdio-common/tst-printf.out > /dev/null 2>&1 ||
diff --git a/src/patches/glibc/glibc-bz2571.patch b/src/patches/glibc/glibc-bz2571.patch
new file mode 100644 (file)
index 0000000..782c498
--- /dev/null
@@ -0,0 +1,53 @@
+2006-04-25  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2571]
+       * nscd/nscd_helper.c (__nscd_get_map_ref): Make mapptr argument a
+       volatile pointer so that the mapptr->mapped value is re-read after
+       the lock is retrieved.
+       * nscd/nscd-client.h: Update __nscd_get_map_ref prototype.
+
+--- libc/nscd/nscd-client.h    22 Nov 2005 19:03:50 -0000      1.21
++++ libc/nscd/nscd-client.h    25 Apr 2006 23:48:55 -0000      1.22
+@@ -277,7 +277,7 @@ extern int __nscd_open_socket (const cha
+ /* Get reference of mapping.  */
+ extern struct mapped_database *__nscd_get_map_ref (request_type type,
+                                                  const char *name,
+-                                                 struct locked_map_ptr *mapptr,
++                                                 volatile struct locked_map_ptr *mapptr,
+                                                  int *gc_cyclep);
+ /* Unmap database.  */
+--- libc/nscd/nscd_helper.c    2 Apr 2006 18:22:23 -0000       1.15
++++ libc/nscd/nscd_helper.c    25 Apr 2006 23:47:53 -0000      1.16
+@@ -316,17 +316,18 @@ get_mapping (request_type type, const ch
+ struct mapped_database *
+ __nscd_get_map_ref (request_type type, const char *name,
+-                  struct locked_map_ptr *mapptr, int *gc_cyclep)
++                  volatile struct locked_map_ptr *mapptr, int *gc_cyclep)
+ {
+   struct mapped_database *cur = mapptr->mapped;
+   if (cur == NO_MAPPING)
+     return cur;
+   int cnt = 0;
+-  while (atomic_compare_and_exchange_val_acq (&mapptr->lock, 1, 0) != 0)
++  while (__builtin_expect (atomic_compare_and_exchange_val_acq (&mapptr->lock,
++                                                              1, 0) != 0, 0))
+     {
+       // XXX Best number of rounds?
+-      if (++cnt > 5)
++      if (__builtin_expect (++cnt > 5, 0))
+       return NO_MAPPING;
+       atomic_delay ();
+@@ -340,7 +341,8 @@ __nscd_get_map_ref (request_type type, c
+       if (cur == NULL
+         || (cur->head->nscd_certainly_running == 0
+             && cur->head->timestamp + MAPPING_TIMEOUT < time (NULL)))
+-      cur = get_mapping (type, name, &mapptr->mapped);
++      cur = get_mapping (type, name,
++                         (struct mapped_database **) &mapptr->mapped);
+       if (__builtin_expect (cur != NO_MAPPING, 1))
+       {
diff --git a/src/patches/glibc/glibc-bz2592.patch b/src/patches/glibc/glibc-bz2592.patch
new file mode 100644 (file)
index 0000000..aafad64
--- /dev/null
@@ -0,0 +1,447 @@
+2006-09-24  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/ieee754/ldbl-128/s_lrintl.c (__lrintl): Fix 2 typos.
+
+2006-09-20  Andreas Jaeger  <aj@suse.de>
+
+       * math/libm-test.inc (lrint_test_upward): Fix typo.
+
+2006-06-17  Joseph S. Myers  <joseph@codesourcery.com>
+
+       [BZ #2592]
+       * math/libm-test.inc (lrint_test_tonearest): New function.
+       (lrint_test_towardzero): New function.
+       (lrint_test_downward): New function.
+       (lrint_test_upward): New function.
+       (main): Run these new tests.
+       * sysdeps/ieee754/dbl-64/s_llrint.c (__llrint): Correct rounding
+       of values near to 0.
+       (two52): Use double not long double.
+       * sysdeps/ieee754/dbl-64/s_lrint.c (__lrint): Likewise.
+       * sysdeps/ieee754/flt-32/s_llrintf.c (__llrintf): Likewise.
+       (two23): Use float not double.
+       * sysdeps/ieee754/flt-32/s_lrintf.c (__lrintf): Likewise.
+       (two23): Use float not double.
+       * sysdeps/ieee754/ldbl-128/s_llrintl.c (__llrintl): Likewise.
+       * sysdeps/ieee754/ldbl-128/s_lrintl.c (__lrintl): Likewise.
+       * sysdeps/ieee754/ldbl-96/s_llrintl.c (__llrintl): Likewise.
+       * sysdeps/ieee754/ldbl-96/s_lrintl.c (__lrintl): Likewise.
+
+--- libc/math/libm-test.inc    16 Mar 2006 23:16:56 -0000      1.71
++++ libc/math/libm-test.inc    20 Sep 2006 19:36:26 -0000      1.73
+@@ -3273,6 +3273,166 @@ lrint_test (void)
+ static void
++lrint_test_tonearest (void)
++{
++  int save_round_mode;
++  START (lrint_tonearest);
++
++  save_round_mode = fegetround ();
++
++  if (!fesetround (FE_TONEAREST))
++    {
++      TEST_f_l (lrint, 0.0, 0);
++      TEST_f_l (lrint, minus_zero, 0);
++      TEST_f_l (lrint, 0.2L, 0);
++      TEST_f_l (lrint, -0.2L, 0);
++      TEST_f_l (lrint, 0.5L, 0);
++      TEST_f_l (lrint, -0.5L, 0);
++      TEST_f_l (lrint, 0.8L, 1);
++      TEST_f_l (lrint, -0.8L, -1);
++
++      TEST_f_l (lrint, 1.4L, 1);
++      TEST_f_l (lrint, -1.4L, -1);
++
++      TEST_f_l (lrint, 8388600.3L, 8388600);
++      TEST_f_l (lrint, -8388600.3L, -8388600);
++
++      TEST_f_l (lrint, 1071930.0008, 1071930);
++#ifndef TEST_FLOAT
++      TEST_f_l (lrint, 1073741824.01, 1073741824);
++# if LONG_MAX > 281474976710656
++      TEST_f_l (lrint, 281474976710656.025, 281474976710656);
++# endif
++#endif
++    }
++
++  fesetround (save_round_mode);
++
++  END (lrint_tonearest);
++}
++
++
++static void
++lrint_test_towardzero (void)
++{
++  int save_round_mode;
++  START (lrint_towardzero);
++
++  save_round_mode = fegetround ();
++
++  if (!fesetround (FE_TOWARDZERO))
++    {
++      TEST_f_l (lrint, 0.0, 0);
++      TEST_f_l (lrint, minus_zero, 0);
++      TEST_f_l (lrint, 0.2L, 0);
++      TEST_f_l (lrint, -0.2L, 0);
++      TEST_f_l (lrint, 0.5L, 0);
++      TEST_f_l (lrint, -0.5L, 0);
++      TEST_f_l (lrint, 0.8L, 0);
++      TEST_f_l (lrint, -0.8L, 0);
++
++      TEST_f_l (lrint, 1.4L, 1);
++      TEST_f_l (lrint, -1.4L, -1);
++
++      TEST_f_l (lrint, 8388600.3L, 8388600);
++      TEST_f_l (lrint, -8388600.3L, -8388600);
++
++      TEST_f_l (lrint, 1071930.0008, 1071930);
++#ifndef TEST_FLOAT
++      TEST_f_l (lrint, 1073741824.01, 1073741824);
++# if LONG_MAX > 281474976710656
++      TEST_f_l (lrint, 281474976710656.025, 281474976710656);
++# endif
++#endif
++    }
++
++  fesetround (save_round_mode);
++
++  END (lrint_towardzero);
++}
++
++
++static void
++lrint_test_downward (void)
++{
++  int save_round_mode;
++  START (lrint_downward);
++
++  save_round_mode = fegetround ();
++
++  if (!fesetround (FE_DOWNWARD))
++    {
++      TEST_f_l (lrint, 0.0, 0);
++      TEST_f_l (lrint, minus_zero, 0);
++      TEST_f_l (lrint, 0.2L, 0);
++      TEST_f_l (lrint, -0.2L, -1);
++      TEST_f_l (lrint, 0.5L, 0);
++      TEST_f_l (lrint, -0.5L, -1);
++      TEST_f_l (lrint, 0.8L, 0);
++      TEST_f_l (lrint, -0.8L, -1);
++
++      TEST_f_l (lrint, 1.4L, 1);
++      TEST_f_l (lrint, -1.4L, -2);
++
++      TEST_f_l (lrint, 8388600.3L, 8388600);
++      TEST_f_l (lrint, -8388600.3L, -8388601);
++
++      TEST_f_l (lrint, 1071930.0008, 1071930);
++#ifndef TEST_FLOAT
++      TEST_f_l (lrint, 1073741824.01, 1073741824);
++# if LONG_MAX > 281474976710656
++      TEST_f_l (lrint, 281474976710656.025, 281474976710656);
++# endif
++#endif
++    }
++
++  fesetround (save_round_mode);
++
++  END (lrint_downward);
++}
++
++
++static void
++lrint_test_upward (void)
++{
++  int save_round_mode;
++  START (lrint_upward);
++
++  save_round_mode = fegetround ();
++
++  if (!fesetround (FE_UPWARD))
++    {
++      TEST_f_l (lrint, 0.0, 0);
++      TEST_f_l (lrint, minus_zero, 0);
++      TEST_f_l (lrint, 0.2L, 1);
++      TEST_f_l (lrint, -0.2L, 0);
++      TEST_f_l (lrint, 0.5L, 1);
++      TEST_f_l (lrint, -0.5L, 0);
++      TEST_f_l (lrint, 0.8L, 1);
++      TEST_f_l (lrint, -0.8L, 0);
++
++      TEST_f_l (lrint, 1.4L, 2);
++      TEST_f_l (lrint, -1.4L, -1);
++
++      TEST_f_l (lrint, 8388600.3L, 8388601);
++      TEST_f_l (lrint, -8388600.3L, -8388600);
++
++#ifndef TEST_FLOAT
++      TEST_f_l (lrint, 1071930.0008, 1071931);
++      TEST_f_l (lrint, 1073741824.01, 1073741825);
++# if LONG_MAX > 281474976710656 && defined (TEST_LDOUBLE)
++      TEST_f_l (lrint, 281474976710656.025, 281474976710656);
++# endif
++#endif
++    }
++
++  fesetround (save_round_mode);
++
++  END (lrint_upward);
++}
++
++
++static void
+ llrint_test (void)
+ {
+   /* XXX this test is incomplete.  We need to have a way to specifiy
+@@ -5937,6 +6097,10 @@ main (int argc, char **argv)
+   rint_test_downward ();
+   rint_test_upward ();
+   lrint_test ();
++  lrint_test_tonearest ();
++  lrint_test_towardzero ();
++  lrint_test_downward ();
++  lrint_test_upward ();
+   llrint_test ();
+   llrint_test_tonearest ();
+   llrint_test_towardzero ();
+--- libc/sysdeps/ieee754/dbl-64/s_llrint.c     1 Feb 2004 19:20:22 -0000       1.3
++++ libc/sysdeps/ieee754/dbl-64/s_llrint.c     20 Sep 2006 17:14:24 -0000      1.4
+@@ -23,7 +23,7 @@
+ #include "math_private.h"
+-static const long double two52[2] =
++static const double two52[2] =
+ {
+   4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+  -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
+@@ -48,19 +48,14 @@ __llrint (double x)
+   if (j0 < 20)
+     {
+-      if (j0 < -1)
+-      return 0;
+-      else
+-      {
+-        w = two52[sx] + x;
+-        t = w - two52[sx];
+-        EXTRACT_WORDS (i0, i1, t);
+-        j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
+-        i0 &= 0xfffff;
+-        i0 |= 0x100000;
++      w = two52[sx] + x;
++      t = w - two52[sx];
++      EXTRACT_WORDS (i0, i1, t);
++      j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
++      i0 &= 0xfffff;
++      i0 |= 0x100000;
+-        result = i0 >> (20 - j0);
+-      }
++      result = (j0 < 0 ? 0 : i0 >> (20 - j0));
+     }
+   else if (j0 < (int32_t) (8 * sizeof (long long int)) - 1)
+     {
+--- libc/sysdeps/ieee754/dbl-64/s_lrint.c      1 Feb 2004 19:01:03 -0000       1.3
++++ libc/sysdeps/ieee754/dbl-64/s_lrint.c      20 Sep 2006 17:14:24 -0000      1.4
+@@ -48,19 +48,14 @@ __lrint (double x)
+   if (j0 < 20)
+     {
+-      if (j0 < -1)
+-      return 0;
+-      else
+-      {
+-        w = two52[sx] + x;
+-        t = w - two52[sx];
+-        EXTRACT_WORDS (i0, i1, t);
+-        j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
+-        i0 &= 0xfffff;
+-        i0 |= 0x100000;
++      w = two52[sx] + x;
++      t = w - two52[sx];
++      EXTRACT_WORDS (i0, i1, t);
++      j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
++      i0 &= 0xfffff;
++      i0 |= 0x100000;
+-        result = i0 >> (20 - j0);
+-      }
++      result = (j0 < 0 ? 0 : i0 >> (20 - j0));
+     }
+   else if (j0 < (int32_t) (8 * sizeof (long int)) - 1)
+     {
+--- libc/sysdeps/ieee754/flt-32/s_llrintf.c    6 Jul 2001 04:55:55 -0000       1.2
++++ libc/sysdeps/ieee754/flt-32/s_llrintf.c    20 Sep 2006 17:14:24 -0000      1.3
+@@ -23,7 +23,7 @@
+ #include "math_private.h"
+-static const double two23[2] =
++static const float two23[2] =
+ {
+   8.3886080000e+06, /* 0x4B000000 */
+  -8.3886080000e+06, /* 0xCB000000 */
+@@ -49,9 +49,7 @@ __llrintf (float x)
+   if (j0 < (int32_t) (sizeof (long long int) * 8) - 1)
+     {
+-      if (j0 < -1)
+-      return 0;
+-      else if (j0 >= 23)
++      if (j0 >= 23)
+       result = (long long int) i0 << (j0 - 23);
+       else
+       {
+@@ -62,7 +60,7 @@ __llrintf (float x)
+         i0 &= 0x7fffff;
+         i0 |= 0x800000;
+-        result = i0 >> (23 - j0);
++        result = (j0 < 0 ? 0 : i0 >> (23 - j0));
+       }
+     }
+   else
+--- libc/sysdeps/ieee754/flt-32/s_lrintf.c     6 Jul 2001 04:55:55 -0000       1.2
++++ libc/sysdeps/ieee754/flt-32/s_lrintf.c     20 Sep 2006 17:14:24 -0000      1.3
+@@ -23,7 +23,7 @@
+ #include "math_private.h"
+-static const double two23[2] =
++static const float two23[2] =
+ {
+   8.3886080000e+06, /* 0x4B000000 */
+  -8.3886080000e+06, /* 0xCB000000 */
+@@ -49,9 +49,7 @@ __lrintf (float x)
+   if (j0 < (int32_t) (sizeof (long int) * 8) - 1)
+     {
+-      if (j0 < -1)
+-      return 0;
+-      else if (j0 >= 23)
++      if (j0 >= 23)
+       result = (long int) i0 << (j0 - 23);
+       else
+       {
+@@ -62,7 +60,7 @@ __lrintf (float x)
+         i0 &= 0x7fffff;
+         i0 |= 0x800000;
+-        result = i0 >> (23 - j0);
++        result = (j0 < 0 ? 0 : i0 >> (23 - j0));
+       }
+     }
+   else
+--- libc/sysdeps/ieee754/ldbl-128/s_llrintl.c  1 Feb 2006 19:42:43 -0000       1.3
++++ libc/sysdeps/ieee754/ldbl-128/s_llrintl.c  20 Sep 2006 17:14:24 -0000      1.4
+@@ -48,8 +48,6 @@ __llrintl (long double x)
+   if (j0 < (int32_t) (8 * sizeof (long long int)) - 1)
+     {
+-      if (j0 < -1)
+-      return 0;
+       w = two112[sx] + x;
+       t = w - two112[sx];
+       GET_LDOUBLE_WORDS64 (i0, i1, t);
+@@ -57,7 +55,9 @@ __llrintl (long double x)
+       i0 &= 0x0000ffffffffffffLL;
+       i0 |= 0x0001000000000000LL;
+-      if (j0 <= 48)
++      if (j0 < 0)
++      result = 0;
++      else if (j0 <= 48)
+       result = i0 >> (48 - j0);
+       else
+       result = ((long long int) i0 << (j0 - 48)) | (i1 >> (112 - j0));
+--- libc/sysdeps/ieee754/ldbl-128/s_lrintl.c   12 Feb 2004 20:57:40 -0000      1.3
++++ libc/sysdeps/ieee754/ldbl-128/s_lrintl.c   25 Sep 2006 14:11:26 -0000      1.5
+@@ -48,19 +48,14 @@ __lrintl (long double x)
+   if (j0 < 48)
+     {
+-      if (j0 < -1)
+-      return 0;
+-      else
+-      {
+-        w = two112[sx] + x;
+-        t = w - two112[sx];
+-        GET_LDOUBLE_WORDS64 (i0, i1, x);
+-        j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
+-        i0 &= 0x0000ffffffffffffLL;
+-        i0 |= 0x0001000000000000LL;
++      w = two112[sx] + x;
++      t = w - two112[sx];
++      GET_LDOUBLE_WORDS64 (i0, i1, t);
++      j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
++      i0 &= 0x0000ffffffffffffLL;
++      i0 |= 0x0001000000000000LL;
+-        result = i0 >> (48 - j0);
+-      }
++      result = (j0 < 0 ? 0 : i0 >> (48 - j0));
+     }
+   else if (j0 < (int32_t) (8 * sizeof (long int)) - 1)
+     {
+@@ -70,7 +65,7 @@ __lrintl (long double x)
+       {
+         w = two112[sx] + x;
+         t = w - two112[sx];
+-        GET_LDOUBLE_WORDS64 (i0, i1, x);
++        GET_LDOUBLE_WORDS64 (i0, i1, t);
+         j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
+         i0 &= 0x0000ffffffffffffLL;
+         i0 |= 0x0001000000000000LL;
+--- libc/sysdeps/ieee754/ldbl-96/s_llrintl.c   12 Feb 2004 20:57:52 -0000      1.3
++++ libc/sysdeps/ieee754/ldbl-96/s_llrintl.c   20 Sep 2006 17:14:24 -0000      1.4
+@@ -47,9 +47,7 @@ __llrintl (long double x)
+   if (j0 < (int32_t) (8 * sizeof (long long int)) - 1)
+     {
+-      if (j0 < -1)
+-      return 0;
+-      else if (j0 >= 63)
++      if (j0 >= 63)
+       result = (((long long int) i0 << 32) | i1) << (j0 - 63);
+       else
+       {
+@@ -58,7 +56,9 @@ __llrintl (long double x)
+         GET_LDOUBLE_WORDS (se, i0, i1, t);
+         j0 = (se & 0x7fff) - 0x3fff;
+-        if (j0 <= 31)
++        if (j0 < 0)
++          result = 0;
++        else if (j0 <= 31)
+           result = i0 >> (31 - j0);
+         else
+           result = ((long long int) i0 << (j0 - 31)) | (i1 >> (63 - j0));
+--- libc/sysdeps/ieee754/ldbl-96/s_lrintl.c    1 Feb 2004 19:11:52 -0000       1.3
++++ libc/sysdeps/ieee754/ldbl-96/s_lrintl.c    20 Sep 2006 17:14:24 -0000      1.4
+@@ -47,17 +47,12 @@ __lrintl (long double x)
+   if (j0 < 31)
+     {
+-      if (j0 < -1)
+-      return 0;
+-      else
+-      {
+-        w = two63[sx] + x;
+-        t = w - two63[sx];
+-        GET_LDOUBLE_WORDS (se, i0, i1, t);
+-        j0 = (se & 0x7fff) - 0x3fff;
++      w = two63[sx] + x;
++      t = w - two63[sx];
++      GET_LDOUBLE_WORDS (se, i0, i1, t);
++      j0 = (se & 0x7fff) - 0x3fff;
+-        result = i0 >> (31 - j0);
+-      }
++      result = (j0 < 0 ? 0 : i0 >> (31 - j0));
+     }
+   else if (j0 < (int32_t) (8 * sizeof (long int)) - 1)
+     {
diff --git a/src/patches/glibc/glibc-bz2632.patch b/src/patches/glibc/glibc-bz2632.patch
new file mode 100644 (file)
index 0000000..a53ccce
--- /dev/null
@@ -0,0 +1,17 @@
+2006-05-02  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2632]
+       * nscd/connections.c (nscd_init): Correct initialization of
+       in-memory database structure.
+
+--- libc/nscd/connections.c    27 Apr 2006 20:33:32 -0000      1.87
++++ libc/nscd/connections.c    2 May 2006 16:42:58 -0000       1.88
+@@ -722,7 +722,7 @@ cannot set socket to close on exec: %s; 
+           dbs[cnt].head = xmalloc (sizeof (struct database_pers_head)
+                                    + (dbs[cnt].suggested_module
+                                       * sizeof (ref_t)));
+-          memset (dbs[cnt].head, '\0', sizeof (dbs[cnt].head));
++          memset (dbs[cnt].head, '\0', sizeof (struct database_pers_head));
+           assert (~ENDREF == 0);
+           memset (dbs[cnt].head->array, '\xff',
+                   dbs[cnt].suggested_module * sizeof (ref_t));
diff --git a/src/patches/glibc/glibc-bz2644.patch b/src/patches/glibc/glibc-bz2644.patch
new file mode 100644 (file)
index 0000000..e4e4a66
--- /dev/null
@@ -0,0 +1,35 @@
+2006-05-09  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2644]
+       * sysdeps/pthread/unwind-forcedunwind.c: Different solution for
+       the reload problem.  Change the one path in pthread_cancel_init
+       which causes the problem.  Force gcc to reload.  Simplify callers.
+
+2006-05-07  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2644]
+       * sysdeps/pthread/unwind-forcedunwind.c: Make sure functions
+       pointers are reloaded after pthread_cancel_init calls.
+
+--- libc/nptl/sysdeps/pthread/unwind-forcedunwind.c    16 Nov 2005 23:31:28 -0000      1.2
++++ libc/nptl/sysdeps/pthread/unwind-forcedunwind.c    9 May 2006 15:20:39 -0000       1.6
+@@ -31,13 +31,18 @@ static _Unwind_Reason_Code (*libgcc_s_fo
+ static _Unwind_Word (*libgcc_s_getcfa) (struct _Unwind_Context *);
+ void
++__attribute_noinline__
+ pthread_cancel_init (void)
+ {
+   void *resume, *personality, *forcedunwind, *getcfa;
+   void *handle;
+   if (__builtin_expect (libgcc_s_getcfa != NULL, 1))
+-    return;
++    {
++      /* Force gcc to reload all values.  */
++      asm volatile ("" ::: "memory");
++      return;
++    }
+   handle = __libc_dlopen ("libgcc_s.so.1");
diff --git a/src/patches/glibc/glibc-bz2680.patch b/src/patches/glibc/glibc-bz2680.patch
new file mode 100644 (file)
index 0000000..10ada67
--- /dev/null
@@ -0,0 +1,17 @@
+2006-05-21  Joseph S. Myers  <joseph@codesourcery.com>
+
+       [BZ #2680]
+       * posix/unistd.h (getlogin_r): Condition on __USE_POSIX199506, not
+       __USE_UNIX98.
+
+--- libc/posix/unistd.h        1 Apr 2006 19:11:33 -0000       1.146
++++ libc/posix/unistd.h        24 Aug 2006 06:46:27 -0000      1.147
+@@ -811,7 +811,7 @@ extern int tcsetpgrp (int __fd, __pid_t 
+    This function is a possible cancellation points and therefore not
+    marked with __THROW.  */
+ extern char *getlogin (void);
+-#if defined __USE_REENTRANT || defined __USE_UNIX98
++#if defined __USE_REENTRANT || defined __USE_POSIX199506
+ /* Return at most NAME_LEN characters of the login name of the user in NAME.
+    If it cannot be determined or some other error occurred, return the error
+    code.  Otherwise return 0.
diff --git a/src/patches/glibc/glibc-bz2684.patch b/src/patches/glibc/glibc-bz2684.patch
new file mode 100644 (file)
index 0000000..4f4e345
--- /dev/null
@@ -0,0 +1,39 @@
+2006-08-27  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2684]
+       * malloc/malloc.c (public_rEALLOc): Try harder by using other
+       arenas if allocation failed.
+       Patch mostly by Jan Edler <jan.edler@indexengines.com>.
+
+--- libc/malloc/malloc.c       27 Aug 2006 04:37:30 -0000      1.165
++++ libc/malloc/malloc.c       28 Aug 2006 00:57:31 -0000      1.166
+@@ -3625,6 +3625,29 @@ public_rEALLOc(Void_t* oldmem, size_t by
+   (void)mutex_unlock(&ar_ptr->mutex);
+   assert(!newp || chunk_is_mmapped(mem2chunk(newp)) ||
+        ar_ptr == arena_for_chunk(mem2chunk(newp)));
++
++  if (newp == NULL)
++    {
++      /* Try harder to allocate memory in other arenas.  */
++      newp = public_mALLOc(bytes);
++      if (newp != NULL)
++      {
++        MALLOC_COPY (newp, oldmem, oldsize - 2 * SIZE_SZ);
++#if THREAD_STATS
++        if(!mutex_trylock(&ar_ptr->mutex))
++          ++(ar_ptr->stat_lock_direct);
++        else {
++          (void)mutex_lock(&ar_ptr->mutex);
++          ++(ar_ptr->stat_lock_wait);
++        }
++#else
++        (void)mutex_lock(&ar_ptr->mutex);
++#endif
++        _int_free(ar_ptr, oldmem);
++        (void)mutex_unlock(&ar_ptr->mutex);
++      }
++    }
++
+   return newp;
+ }
+ #ifdef libc_hidden_def
diff --git a/src/patches/glibc/glibc-bz2703.patch b/src/patches/glibc/glibc-bz2703.patch
new file mode 100644 (file)
index 0000000..708bc39
--- /dev/null
@@ -0,0 +1,113 @@
+2006-06-04  Ulrich Drepper  <drepper@redhat.com>
+
+       * string/Makefile (tests): Add bug-envz1.
+       * string/bug-enz1.c: New file.
+
+2006-06-02  Ryan S. Arnold  <rsa@us.ibm.com>
+
+       [BZ #2703]
+       * string/envz.c (envz_strip): Correct erroneously reversed src
+       and dest parameters to memmove() invocation.
+
+--- libc/string/Makefile       4 Apr 2006 08:40:42 -0000       1.68
++++ libc/string/Makefile       4 Jun 2006 16:35:25 -0000       1.69
+@@ -53,7 +53,8 @@ tests                := tester inl-tester noinl-tester
+                  tst-strlen stratcliff tst-svc tst-inlcall            \
+                  bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap      \
+                  tst-strtok tst-strxfrm bug-strcoll1 tst-strfry       \
+-                 bug-strtok1 $(addprefix test-,$(strop-tests))
++                 bug-strtok1 $(addprefix test-,$(strop-tests))        \
++                 bug-envz1
+ distribute    := memcopy.h pagecopy.h tst-svc.expect test-string.h
+--- libc/string/bug-envz1.c    1 Jan 1970 00:00:00 -0000
++++ libc/string/bug-envz1.c    4 Jun 2006 16:35:21 -0000       1.1
+@@ -0,0 +1,76 @@
++/* Test for bug BZ #2703.  */
++#include <stdio.h>
++#include <envz.h>
++#include <stdlib.h>
++#include <string.h>
++
++static const struct
++{
++  const char *s;
++  int in_result;
++} strs[] =
++{
++  { "a=1", 1 },
++  { "b=2", 1 },
++  { "(*)", 0 },
++  { "(*)", 0 },
++  { "e=5", 1 },
++  { "f=", 1 },
++  { "(*)", 0 },
++  { "h=8", 1 },
++  { "i=9", 1 },
++  { "j", 0 }
++};
++
++#define nstrs (sizeof (strs) / sizeof (strs[0]))
++
++
++static int
++do_test (void)
++{
++
++  size_t size = 0;
++  char *str = malloc (100);
++  if (str == NULL)
++    {
++      puts ("out of memory");
++      return 1;
++    }
++
++  char **argz = &str;
++
++  for (int i = 0; i < nstrs; ++i)
++    argz_add_sep (argz, &size, strs[i].s, '\0');
++
++  printf ("calling envz_strip with size=%zu\n", size);
++  envz_strip (argz, &size);
++
++  int result = 0;
++  printf ("new size=%zu\n", size);
++  for (int i = 0; i < nstrs; ++i)
++    if (strs[i].in_result)
++      {
++        char name[2];
++        name[0] = strs[i].s[0];
++        name[1] = '\0';
++
++        char *e = envz_entry (*argz, size, name);
++        if (e == NULL)
++          {
++            printf ("entry '%s' not found\n", name);
++            result = 1;
++          }
++        else if (strcmp (e, strs[i].s) != 0)
++          {
++            printf ("entry '%s' does not match: is '%s', expected '%s'\n",
++                    name, e, strs[i].s);
++            result = 1;
++          }
++      }
++
++  free (*argz);
++  return result;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/string/envz.c 6 Aug 2002 06:08:16 -0000       1.13
++++ libc/string/envz.c 4 Jun 2006 04:34:14 -0000       1.14
+@@ -165,7 +165,7 @@ envz_strip (char **envz, size_t *envz_le
+       left -= entry_len;
+       if (! strchr (entry, SEP))
+       /* Null entry. */
+-      memmove (entry + entry_len, entry, left);
++      memmove (entry, entry + entry_len, left);
+       else
+       entry += entry_len;
+     }
diff --git a/src/patches/glibc/glibc-bz2766.patch b/src/patches/glibc/glibc-bz2766.patch
new file mode 100644 (file)
index 0000000..d13c5b1
--- /dev/null
@@ -0,0 +1,111 @@
+2006-06-14  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #2766]
+       * misc/insremque.c (insque): Handle prev == NULL.
+       * misc/Makefile (tests): Add tst-insremque.
+       * misc/tst-insremque.c: New test.
+
+--- libc/misc/Makefile 23 Feb 2006 22:50:16 -0000      1.118
++++ libc/misc/Makefile 17 Jun 2006 17:00:58 -0000      1.119
+@@ -76,7 +76,7 @@ endif
+ gpl2lgpl := error.c error.h
+ tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
+-       tst-error1
++       tst-error1 tst-insremque
+ ifeq (no,$(cross-compiling))
+ tests: $(objpfx)tst-error1-mem
+ endif
+--- libc/misc/insremque.c      6 Jul 2001 04:55:36 -0000       1.4
++++ libc/misc/insremque.c      17 Jun 2006 16:59:34 -0000      1.5
+@@ -24,12 +24,20 @@
+ void
+ insque (void *elem, void *prev)
+ {
+-  struct qelem *next = ((struct qelem *) prev)->q_forw;
+-  ((struct qelem *) prev)->q_forw = (struct qelem *) elem;
+-  if (next != NULL)
+-    next->q_back = (struct qelem *) elem;
+-  ((struct qelem *) elem)->q_forw = next;
+-  ((struct qelem *) elem)->q_back = (struct qelem *) prev;
++  if (prev == NULL)
++    {
++      ((struct qelem *) elem)->q_forw = NULL;
++      ((struct qelem *) elem)->q_back = NULL;
++    }
++  else
++    {
++      struct qelem *next = ((struct qelem *) prev)->q_forw;
++      ((struct qelem *) prev)->q_forw = (struct qelem *) elem;
++      if (next != NULL)
++      next->q_back = (struct qelem *) elem;
++      ((struct qelem *) elem)->q_forw = next;
++      ((struct qelem *) elem)->q_back = (struct qelem *) prev;
++    }
+ }
+ /* Unlink ELEM from the doubly-linked list that it is in.  */
+--- libc/misc/tst-insremque.c  1 Jan 1970 00:00:00 -0000
++++ libc/misc/tst-insremque.c  17 Jun 2006 17:00:08 -0000      1.1
+@@ -0,0 +1,61 @@
++#include <search.h>
++#include <stdio.h>
++#include <string.h>
++
++#define CHECK(cond) \
++  do                                                                  \
++    if (! (cond))                                                     \
++      {                                                                       \
++      printf ("Condition " #cond " not true on line %d\n", __LINE__); \
++      ret = 1;                                                        \
++      }                                                                       \
++  while (0)
++
++static int
++do_test (void)
++{
++  struct qelem elements[4];
++  int ret = 0;
++
++  /* Linear list.  */
++  memset (elements, 0xff, sizeof (elements));
++  insque (&elements[0], NULL);
++  remque (&elements[0]);
++  insque (&elements[0], NULL);
++  insque (&elements[2], &elements[0]);
++  insque (&elements[1], &elements[0]);
++  insque (&elements[3], &elements[2]);
++  remque (&elements[2]);
++  insque (&elements[2], &elements[0]);
++  CHECK (elements[0].q_back == NULL);
++  CHECK (elements[0].q_forw == &elements[2]);
++  CHECK (elements[1].q_back == &elements[2]);
++  CHECK (elements[1].q_forw == &elements[3]);
++  CHECK (elements[2].q_back == &elements[0]);
++  CHECK (elements[2].q_forw == &elements[1]);
++  CHECK (elements[3].q_back == &elements[1]);
++  CHECK (elements[3].q_forw == NULL);
++
++  /* Circular list.  */
++  memset (elements, 0xff, sizeof (elements));
++  elements[0].q_back = &elements[0];
++  elements[0].q_forw = &elements[0];
++  insque (&elements[2], &elements[0]);
++  insque (&elements[1], &elements[0]);
++  insque (&elements[3], &elements[2]);
++  remque (&elements[2]);
++  insque (&elements[2], &elements[0]);
++  CHECK (elements[0].q_back == &elements[3]);
++  CHECK (elements[0].q_forw == &elements[2]);
++  CHECK (elements[1].q_back == &elements[2]);
++  CHECK (elements[1].q_forw == &elements[3]);
++  CHECK (elements[2].q_back == &elements[0]);
++  CHECK (elements[2].q_forw == &elements[1]);
++  CHECK (elements[3].q_back == &elements[1]);
++  CHECK (elements[3].q_forw == &elements[0]);
++
++  return ret;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-bz2775.patch b/src/patches/glibc/glibc-bz2775.patch
new file mode 100644 (file)
index 0000000..e015507
--- /dev/null
@@ -0,0 +1,32 @@
+2006-09-07  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #2775]
+       * malloc/malloc.c (sYSMALLOc): Only call grow_heap if
+       (long) (MINSIZE + nb - old_size) is positive.
+
+       * malloc/arena.c (grow_heap): When growing bail even if new_size
+       is negative.
+
+--- libc/malloc/arena.c        22 Aug 2006 06:39:51 -0000      1.23
++++ libc/malloc/arena.c        7 Sep 2006 16:04:22 -0000       1.24
+@@ -712,7 +712,7 @@ grow_heap(h, diff) heap_info *h; long di
+   if(diff >= 0) {
+     diff = (diff + page_mask) & ~page_mask;
+     new_size = (long)h->size + diff;
+-    if(new_size > HEAP_MAX_SIZE)
++    if((unsigned long) new_size > (unsigned long) HEAP_MAX_SIZE)
+       return -1;
+     if(mprotect((char *)h + h->size, diff, PROT_READ|PROT_WRITE) != 0)
+       return -2;
+--- libc/malloc/malloc.c       28 Aug 2006 00:57:31 -0000      1.167
++++ libc/malloc/malloc.c       7 Sep 2006 16:06:02 -0000       1.168
+@@ -2970,7 +2970,8 @@ static Void_t* sYSMALLOc(nb, av) INTERNA
+     /* First try to extend the current heap. */
+     old_heap = heap_for_ptr(old_top);
+     old_heap_size = old_heap->size;
+-    if (grow_heap(old_heap, MINSIZE + nb - old_size) == 0) {
++    if ((long) (MINSIZE + nb - old_size) > 0
++      && grow_heap(old_heap, MINSIZE + nb - old_size) == 0) {
+       av->system_mem += old_heap->size - old_heap_size;
+       arena_mem += old_heap->size - old_heap_size;
+ #if 0
diff --git a/src/patches/glibc/glibc-bz2792.patch b/src/patches/glibc/glibc-bz2792.patch
new file mode 100644 (file)
index 0000000..6e8962f
--- /dev/null
@@ -0,0 +1,32 @@
+2006-06-17  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2792]
+       * elf/dl-deps.c (expand_dst): Rename __cnt variable to not
+       conflict with DL_DST_REQUIRED.
+
+--- libc/elf/dl-deps.c 18 Jan 2006 19:48:53 -0000      1.81
++++ libc/elf/dl-deps.c 17 Jun 2006 16:51:56 -0000      1.82
+@@ -101,9 +101,9 @@ struct list
+   ({                                                                        \
+     const char *__str = (str);                                                      \
+     const char *__result = __str;                                           \
+-    size_t __cnt = DL_DST_COUNT(__str, 0);                                  \
++    size_t __dst_cnt = DL_DST_COUNT (__str, 0);                                     \
+                                                                             \
+-    if (__cnt != 0)                                                         \
++    if (__dst_cnt != 0)                                                             \
+       {                                                                             \
+       char *__newp;                                                         \
+                                                                             \
+@@ -113,9 +113,9 @@ struct list
+ DST not allowed in SUID/SGID programs"));                                   \
+                                                                             \
+       __newp = (char *) alloca (DL_DST_REQUIRED (l, __str, strlen (__str),  \
+-                                                 __cnt));                   \
++                                                 __dst_cnt));               \
+                                                                             \
+-      __result = _dl_dst_substitute (l, __str, __newp, 0);          \
++      __result = _dl_dst_substitute (l, __str, __newp, 0);                  \
+                                                                             \
+       if (*__result == '\0')                                                \
+         {                                                                   \
diff --git a/src/patches/glibc/glibc-bz2821.patch b/src/patches/glibc/glibc-bz2821.patch
new file mode 100644 (file)
index 0000000..761893b
--- /dev/null
@@ -0,0 +1,55 @@
+2006-09-09  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2821]
+       * time/mktime.c (guess_time_tm): Fix overflow detection.
+       * time/Makefile (tests): Add bug-mktime1.
+       * time/bug-mktime1.c: New file.
+
+--- libc/time/Makefile 14 Oct 2005 15:16:17 -0000      1.109
++++ libc/time/Makefile 9 Sep 2006 16:54:49 -0000       1.110
+@@ -35,7 +35,7 @@ distribute := datemsk
+ tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
+          tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \
+-         tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r
++         tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1
+ include ../Rules
+--- libc/time/bug-mktime1.c    1 Jan 1970 00:00:00 -0000
++++ libc/time/bug-mktime1.c    9 Sep 2006 16:54:23 -0000       1.1
+@@ -0,0 +1,17 @@
++#include <stdio.h>
++#include <time.h>
++
++
++static int
++do_test (void)
++{
++  struct tm t2 = { 0, 0, 0, 1, 1, 2050 - 1900, 1, 1, 1 };
++  time_t tt2 = mktime (&t2);
++  printf ("%ld\n", (long int) tt2);
++  if (sizeof (time_t) == 4 && tt2 != -1)
++    return 1;
++  return 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/time/mktime.c 8 Sep 2005 08:09:07 -0000       1.66
++++ libc/time/mktime.c 9 Sep 2006 16:56:18 -0000       1.67
+@@ -216,10 +216,11 @@ guess_time_tm (long int year, long int y
+   /* Overflow occurred one way or another.  Return the nearest result
+      that is actually in range, except don't report a zero difference
+      if the actual difference is nonzero, as that would cause a false
+-     match.  */
++     match; and don't oscillate between two values, as that would
++     confuse the spring-forward gap detector.  */
+   return (*t < TIME_T_MIDPOINT
+-        ? TIME_T_MIN + (*t == TIME_T_MIN)
+-        : TIME_T_MAX - (*t == TIME_T_MAX));
++        ? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN)
++        : (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX));
+ }
+ /* Use CONVERT to convert *T to a broken down time in *TP.
diff --git a/src/patches/glibc/glibc-bz2841.patch b/src/patches/glibc/glibc-bz2841.patch
new file mode 100644 (file)
index 0000000..88ad720
--- /dev/null
@@ -0,0 +1,20 @@
+2006-06-23  Paul Eggert  <eggert@cs.ucla.edu>
+
+       [BZ #2841]
+       * sysdeps/generic/stdint.h (UINT8_C, UINT16_C): Don't append 'U',
+       since C99 requires the result to promote to 'int' when uint_least8_t
+       and uint_least16_t promote to 'int'.
+
+--- libc/sysdeps/generic/stdint.h      18 Aug 2001 22:15:39 -0000      1.10
++++ libc/sysdeps/generic/stdint.h      12 Aug 2006 21:22:51 -0000      1.11
+@@ -297,8 +297,8 @@ typedef unsigned long long int     uintmax_t
+ # endif
+ /* Unsigned.  */
+-# define UINT8_C(c)   c ## U
+-# define UINT16_C(c)  c ## U
++# define UINT8_C(c)   c
++# define UINT16_C(c)  c
+ # define UINT32_C(c)  c ## U
+ # if __WORDSIZE == 64
+ #  define UINT64_C(c) c ## UL
diff --git a/src/patches/glibc/glibc-bz2843.patch b/src/patches/glibc/glibc-bz2843.patch
new file mode 100644 (file)
index 0000000..f509feb
--- /dev/null
@@ -0,0 +1,359 @@
+2006-08-12  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2843]
+       * pthread_join.c (pthread_join): Account for self being canceled
+       when checking for deadlocks.
+       * tst-join5.c: Cleanups.  Allow to be used in tst-join6.
+       (tf1): Don't print anything after pthread_join returns, this would be
+       another cancellation point.
+       (tf2): Likewise.
+       * tst-join6.c: New file.
+       * Makefile (tests): Add tst-join6.
+
+--- libc/nptl/Makefile 1 Aug 2006 06:05:02 -0000       1.183
++++ libc/nptl/Makefile 13 Aug 2006 01:53:28 -0000      1.184
+@@ -224,7 +224,7 @@ tests = tst-typesizes \
+       tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \
+       tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
+       tst-raise1 \
+-      tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 \
++      tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 \
+       tst-detach1 \
+       tst-eintr1 tst-eintr2 tst-eintr3 tst-eintr4 tst-eintr5 \
+       tst-tsd1 tst-tsd2 tst-tsd3 tst-tsd4 tst-tsd5 \
+--- libc/nptl/pthread_join.c   21 Dec 2005 22:17:21 -0000      1.9
++++ libc/nptl/pthread_join.c   13 Aug 2006 01:54:37 -0000      1.10
+@@ -27,7 +27,11 @@
+ static void
+ cleanup (void *arg)
+ {
+-  *(void **) arg = NULL;
++  /* 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);
+ }
+@@ -36,7 +40,6 @@ pthread_join (threadid, thread_return)
+      pthread_t threadid;
+      void **thread_return;
+ {
+-  struct pthread *self;
+   struct pthread *pd = (struct pthread *) threadid;
+   /* Make sure the descriptor is valid.  */
+@@ -49,12 +52,23 @@ pthread_join (threadid, thread_return)
+     /* We cannot wait for the thread.  */
+     return EINVAL;
+-  self = THREAD_SELF;
+-  if (pd == self
+-      || (self->joinid == pd
+-        && (pd->cancelhandling
+-            & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK
+-               | TERMINATED_BITMASK)) == 0))
++  struct pthread *self = THREAD_SELF;
++  int result = 0;
++
++  /* During the wait we change to asynchronous cancellation.  If we
++     are canceled the thread we are waiting for must be marked as
++     un-wait-ed for again.  */
++  pthread_cleanup_push (cleanup, &pd->joinid);
++
++  /* Switch to asynchronous cancellation.  */
++  int oldtype = CANCEL_ASYNC ();
++
++  if ((pd == self
++       || (self->joinid == pd
++         && (pd->cancelhandling
++             & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK
++                | TERMINATED_BITMASK)) == 0))
++      && !CANCEL_ENABLED_AND_CANCELED (self->cancelhandling))
+     /* This is a deadlock situation.  The threads are waiting for each
+        other to finish.  Note that this is a "may" error.  To be 100%
+        sure we catch this error we would have to lock the data
+@@ -62,28 +76,17 @@ pthread_join (threadid, thread_return)
+        two threads are really caught in this situation they will
+        deadlock.  It is the programmer's problem to figure this
+        out.  */
+-    return EDEADLK;
+-
++    result = EDEADLK;
+   /* Wait for the thread to finish.  If it is already locked something
+      is wrong.  There can only be one waiter.  */
+-  if (__builtin_expect (atomic_compare_and_exchange_bool_acq (&pd->joinid,
+-                                                            self,
+-                                                            NULL), 0))
++  else if (__builtin_expect (atomic_compare_and_exchange_bool_acq (&pd->joinid,
++                                                                 self,
++                                                                 NULL), 0))
+     /* There is already somebody waiting for the thread.  */
+-    return EINVAL;
+-
+-
+-  /* During the wait we change to asynchronous cancellation.  If we
+-     are cancelled the thread we are waiting for must be marked as
+-     un-wait-ed for again.  */
+-  pthread_cleanup_push (cleanup, &pd->joinid);
+-
+-  /* Switch to asynchronous cancellation.  */
+-  int oldtype = CANCEL_ASYNC ();
+-
+-
+-  /* Wait for the child.  */
+-  lll_wait_tid (pd->tid);
++    result = EINVAL;
++  else
++    /* Wait for the child.  */
++    lll_wait_tid (pd->tid);
+   /* Restore cancellation mode.  */
+@@ -93,16 +96,19 @@ pthread_join (threadid, thread_return)
+   pthread_cleanup_pop (0);
+-  /* We mark the thread as terminated and as joined.  */
+-  pd->tid = -1;
++  if (__builtin_expect (result == 0, 1))
++    {
++      /* We mark the thread as terminated and as joined.  */
++      pd->tid = -1;
+-  /* Store the return value if the caller is interested.  */
+-  if (thread_return != NULL)
+-    *thread_return = pd->result;
++      /* Store the return value if the caller is interested.  */
++      if (thread_return != NULL)
++      *thread_return = pd->result;
+-  /* Free the TCB.  */
+-  __free_tcb (pd);
++      /* Free the TCB.  */
++      __free_tcb (pd);
++    }
+-  return 0;
++  return result;
+ }
+--- libc/nptl/tst-join5.c      23 Mar 2003 10:01:40 -0000      1.2
++++ libc/nptl/tst-join5.c      13 Aug 2006 01:52:22 -0000      1.3
+@@ -21,120 +21,187 @@
+ #include <pthread.h>
+ #include <stdio.h>
+ #include <stdlib.h>
++#include <time.h>
++#include <unistd.h>
++#include <sys/syscall.h>
++
++
++#define wait_code()                                                         \
++  do {                                                                              \
++    struct timespec ts = { .tv_sec = 0, .tv_nsec = 200000000 };                     \
++    while (syscall (__NR_nanosleep, &ts, &ts) < 0)                          \
++      /* nothing */;                                                        \
++  } while (0)
++
++
++#ifdef WAIT_IN_CHILD
++static pthread_barrier_t b;
++#endif
+ static void *
+ tf1 (void *arg)
+ {
+-  pthread_join ((pthread_t) arg, NULL);
++#ifdef WAIT_IN_CHILD
++  int e = pthread_barrier_wait (&b);
++  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
++    {
++      printf ("%s: barrier_wait failed\n", __func__);
++      exit (1);
++    }
++
++  wait_code ();
++#endif
+-  puts ("1st join returned");
++  pthread_join ((pthread_t) arg, NULL);
+-  return (void *) 1l;
++  exit (42);
+ }
+ static void *
+ tf2 (void *arg)
+ {
+-  pthread_join ((pthread_t) arg, NULL);
++#ifdef WAIT_IN_CHILD
++  int e = pthread_barrier_wait (&b);
++  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
++    {
++      printf ("%s: barrier_wait failed\n", __func__);
++      exit (1);
++    }
+-  puts ("2nd join returned");
++  wait_code ();
++#endif
++  pthread_join ((pthread_t) arg, NULL);
+-  return (void *) 1l;
++  exit (43);
+ }
+ static int
+ do_test (void)
+ {
++#ifdef WAIT_IN_CHILD
++  if (pthread_barrier_init (&b, NULL, 2) != 0)
++    {
++      puts ("barrier_init failed");
++      return 1;
++    }
++#endif
++
+   pthread_t th;
+   int err = pthread_join (pthread_self (), NULL);
+   if (err == 0)
+     {
+       puts ("1st circular join succeeded");
+-      exit (1);
++      return 1;
+     }
+   if (err != EDEADLK)
+     {
+       printf ("1st circular join %d, not EDEADLK\n", err);
+-      exit (1);
++      return 1;
+     }
+   if (pthread_create (&th, NULL, tf1, (void *) pthread_self ()) != 0)
+     {
+       puts ("1st create failed");
+-      exit (1);
++      return 1;
+     }
++#ifndef WAIT_IN_CHILD
++  wait_code ();
++#endif
++
+   if (pthread_cancel (th) != 0)
+     {
+       puts ("cannot cancel 1st thread");
+-      exit (1);
++      return 1;
+     }
++#ifdef WAIT_IN_CHILD
++  int e = pthread_barrier_wait (&b);
++  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
++    {
++      printf ("%s: barrier_wait failed\n", __func__);
++      return 1;
++    }
++#endif
++
+   void *r;
+   err = pthread_join (th, &r);
+   if (err != 0)
+     {
+       printf ("cannot join 1st thread: %d\n", err);
+-      exit (1);
++      return 1;
+     }
+   if (r != PTHREAD_CANCELED)
+     {
+       puts ("1st thread not canceled");
+-      exit (1);
++      return 1;
+     }
+   err = pthread_join (pthread_self (), NULL);
+   if (err == 0)
+     {
+       puts ("2nd circular join succeeded");
+-      exit (1);
++      return 1;
+     }
+   if (err != EDEADLK)
+     {
+       printf ("2nd circular join %d, not EDEADLK\n", err);
+-      exit (1);
++      return 1;
+     }
+   if (pthread_create (&th, NULL, tf2, (void *) pthread_self ()) != 0)
+     {
+       puts ("2nd create failed");
+-      exit (1);
++      return 1;
+     }
++#ifndef WAIT_IN_CHILD
++  wait_code ();
++#endif
++
+   if (pthread_cancel (th) != 0)
+     {
+       puts ("cannot cancel 2nd thread");
+-      exit (1);
++      return 1;
+     }
++#ifdef WAIT_IN_CHILD
++  e = pthread_barrier_wait (&b);
++  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
++    {
++      printf ("%s: barrier_wait failed\n", __func__);
++      return 1;
++    }
++#endif
++
+   if (pthread_join (th, &r) != 0)
+     {
+       puts ("cannot join 2nd thread");
+-      exit (1);
++      return 1;
+     }
+   if (r != PTHREAD_CANCELED)
+     {
+       puts ("2nd thread not canceled");
+-      exit (1);
++      return 1;
+     }
+   err = pthread_join (pthread_self (), NULL);
+   if (err == 0)
+     {
+-      puts ("2nd circular join succeeded");
+-      exit (1);
++      puts ("3rd circular join succeeded");
++      return 1;
+     }
+   if (err != EDEADLK)
+     {
+-      printf ("2nd circular join %d, not EDEADLK\n", err);
+-      exit (1);
++      printf ("3rd circular join %d, not EDEADLK\n", err);
++      return 1;
+     }
+-  exit (0);
++  return 0;
+ }
+ #define TEST_FUNCTION do_test ()
+--- libc/nptl/tst-join6.c      1 Jan 1970 00:00:00 -0000
++++ libc/nptl/tst-join6.c      13 Aug 2006 01:51:08 -0000      1.1
+@@ -0,0 +1,2 @@
++#define WAIT_IN_CHILD 1
++#include "tst-join5.c"
diff --git a/src/patches/glibc/glibc-bz2892.patch b/src/patches/glibc/glibc-bz2892.patch
new file mode 100644 (file)
index 0000000..a2ecd0b
--- /dev/null
@@ -0,0 +1,19 @@
+2006-08-03  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2892]
+       * pthread_setspecific.c (__pthread_setspecific): Check
+       out-of-range index before checking for unused key.
+
+--- libc/nptl/pthread_setspecific.c    2 Apr 2003 03:41:41 -0000       1.4
++++ libc/nptl/pthread_setspecific.c    3 Aug 2006 09:34:57 -0000       1.5
+@@ -52,8 +52,8 @@ __pthread_setspecific (key, value)
+     }
+   else
+     {
+-      if (KEY_UNUSED ((seq = __pthread_keys[key].seq))
+-        || key >= PTHREAD_KEYS_MAX)
++      if (key >= PTHREAD_KEYS_MAX
++        || KEY_UNUSED ((seq = __pthread_keys[key].seq)))
+       /* Not valid.  */
+       return EINVAL;
diff --git a/src/patches/glibc/glibc-bz2908.patch b/src/patches/glibc/glibc-bz2908.patch
new file mode 100644 (file)
index 0000000..29c74f1
--- /dev/null
@@ -0,0 +1,93 @@
+2006-08-08  Jakub Jelinek  <jakub@redhat.com>
+
+       * stdio-common/bug16.c (tests): New array.
+       (do_tests): Allow the first hexadecimal digit
+       to be 1, 2, 4 or 8.  Do 3 additional tests.
+
+2006-08-03  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2908]
+       * sysdeps/generic/printf_fphex.c (__printf_fphex): When rounding up
+       'f', use '1' as leading digit not '\1'.
+       * stdio-common/Makefile (tests): Add bug16.
+       * stdio-common/bug16.c: New file.
+
+--- libc/stdio-common/Makefile 14 Jan 2006 12:09:45 -0000      1.97
++++ libc/stdio-common/Makefile 3 Aug 2006 09:25:01 -0000       1.98
+@@ -54,7 +54,7 @@ tests := tstscanf test_rdwr test-popen t
+        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
++       tst-fwrite bug16
+ test-srcs = tst-unbputc tst-printf
+--- libc/sysdeps/generic/printf_fphex.c        14 Dec 2005 10:00:09 -0000      1.14
++++ libc/sysdeps/generic/printf_fphex.c        3 Aug 2006 09:37:36 -0000       1.17
+@@ -399,12 +399,15 @@ __printf_fphex (FILE *fp,
+               ++leading;
+             else
+               {
+-                leading = 1;
++                leading = '1';
+                 if (expnegative)
+                   {
+-                    exponent += 4;
+-                    if (exponent >= 0)
+-                      expnegative = 0;
++                    exponent -= 4;
++                    if (exponent <= 0)
++                      {
++                        exponent = -exponent;
++                        expnegative = 0;
++                      }
+                   }
+                 else
+                   exponent += 4;
+--- libc/stdio-common/bug16.c  1 Jan 1970 00:00:00 -0000
++++ libc/stdio-common/bug16.c  8 Aug 2006 15:44:33 -0000       1.2
+@@ -0,0 +1,43 @@
++#include <stdio.h>
++#include <string.h>
++
++struct
++{
++  long double val;
++  const char str[4][7];
++} tests[] =
++{
++  { 0x0.FFFFp+0L, { "0X1P+0", "0X2P-1", "0X4P-2", "0X8P-3" } },
++  { 0x0.FFFFp+1L, { "0X1P+1", "0X2P+0", "0X4P-1", "0X8P-2" } },
++  { 0x0.FFFFp+2L, { "0X1P+2", "0X2P+1", "0X4P+0", "0X8P-1" } },
++  { 0x0.FFFFp+3L, { "0X1P+3", "0X2P+2", "0X4P+1", "0X8P+0" } }
++};
++
++static int
++do_test (void)
++{
++  char buf[100];
++  int ret = 0;
++
++  for (size_t i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
++    {  
++      snprintf (buf, sizeof (buf), "%.0LA", tests[i].val);
++
++      size_t j;
++      for (j = 0; j < 4; ++j)
++      if (strcmp (buf, tests[i].str[j]) == 0)
++        break;
++
++      if (j == 4)
++      {
++        printf ("%zd: got \"%s\", expected \"%s\" or equivalent\n",
++                i, buf, tests[i].str[0]);
++        ret = 1;
++      }
++    }
++
++  return ret;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-bz2998.patch b/src/patches/glibc/glibc-bz2998.patch
new file mode 100644 (file)
index 0000000..ecf8a6e
--- /dev/null
@@ -0,0 +1,19 @@
+2006-08-03  Eric Blake <ebb9@byu.net>
+
+       [BZ #2998]
+       * misc/error.c (error_tail) [_LIBC]: Avoid invalid free.
+
+--- libc/misc/error.c  28 Jul 2005 21:42:37 -0000      1.38
++++ libc/misc/error.c  12 Aug 2006 17:57:29 -0000      1.39
+@@ -224,7 +224,10 @@ error_tail (int status, int errnum, cons
+       {
+         /* The string cannot be converted.  */
+         if (use_malloc)
+-          free (wmessage);
++          {
++            free (wmessage);
++            use_malloc = false;
++          }
+         wmessage = (wchar_t *) L"???";
+       }
diff --git a/src/patches/glibc/glibc-bz3123.patch b/src/patches/glibc/glibc-bz3123.patch
new file mode 100644 (file)
index 0000000..d260929
--- /dev/null
@@ -0,0 +1,297 @@
+2006-09-12  Ulrich Drepper  <drepper@redhat.com>
+
+       * tst-cond22.c (tf): Slight changes to the pthread_cond_wait use
+       to guarantee the thread is always canceled.
+
+2006-09-08  Jakub Jelinek  <jakub@redhat.com>
+
+       * tst-cond22.c: Include pthread.h instead of pthreadP.h.
+       Include stdlib.h.
+       * sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Only
+       increase FUTEX if increasing WAKEUP_SEQ.  Fix comment typo.
+       * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise.
+       * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise.
+       * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise.
+
+2006-09-08  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #3123]
+       * sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Don't
+       increment WAKEUP_SEQ if this would increase the value beyond TOTAL_SEQ.
+       * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise.
+       * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise.
+       * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise.
+       * Makefile (tests): Add tst-cond22.
+       * tst-cond22.c: New file.
+
+--- libc/nptl/Makefile 21 Aug 2006 21:02:10 -0000      1.186
++++ libc/nptl/Makefile 8 Sep 2006 10:40:49 -0000       1.188
+@@ -196,7 +196,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 \
+       tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
+       tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
+       tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
+-      tst-cond20 tst-cond21 \
++      tst-cond20 tst-cond21 tst-cond22 \
+       tst-rwlock1 tst-rwlock2 tst-rwlock3 tst-rwlock4 tst-rwlock5 \
+       tst-rwlock6 tst-rwlock7 tst-rwlock8 tst-rwlock9 tst-rwlock10 \
+       tst-rwlock11 tst-rwlock12 tst-rwlock13 tst-rwlock14 \
+--- libc/nptl/tst-cond22.c     1 Jan 1970 00:00:00 -0000
++++ libc/nptl/tst-cond22.c     12 Sep 2006 12:24:28 -0000      1.5
+@@ -0,0 +1,160 @@
++#include <pthread.h>
++#include <stdio.h>
++#include <stdlib.h>
++
++
++static pthread_barrier_t b;
++static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
++static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
++
++
++static void
++cl (void *arg)
++{
++  pthread_mutex_unlock (&m);
++}
++
++
++static void *
++tf (void *arg)
++{
++  if (pthread_mutex_lock (&m) != 0)
++    {
++      printf ("%s: mutex_lock failed\n", __func__);
++      exit (1);
++    }
++  int e = pthread_barrier_wait (&b);
++  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
++    {
++      printf ("%s: barrier_wait failed\n", __func__);
++      exit (1);
++    }
++  pthread_cleanup_push (cl, NULL);
++  /* We have to loop here because the cancellation might come after
++     the cond_wait call left the cancelable area and is then waiting
++     on the mutex.  In this case the beginning of the second cond_wait
++     call will cause the cancellation to happen.  */
++  do
++    if (pthread_cond_wait (&c, &m) != 0)
++      {
++      printf ("%s: cond_wait failed\n", __func__);
++      exit (1);
++      }
++  while (arg == NULL);
++  pthread_cleanup_pop (0);
++  if (pthread_mutex_unlock (&m) != 0)
++    {
++      printf ("%s: mutex_unlock failed\n", __func__);
++      exit (1);
++    }
++  return NULL;
++}
++
++
++static int
++do_test (void)
++{
++  int status = 0;
++
++  if (pthread_barrier_init (&b, NULL, 2) != 0)
++    {
++      puts ("barrier_init failed");
++      return 1;
++    }
++
++  pthread_t th;
++  if (pthread_create (&th, NULL, tf, NULL) != 0)
++    {
++      puts ("1st create failed");
++      return 1;
++    }
++  int e = pthread_barrier_wait (&b);
++  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
++    {
++      puts ("1st barrier_wait failed");
++      return 1;
++    }
++  if (pthread_mutex_lock (&m) != 0)
++    {
++      puts ("1st mutex_lock failed");
++      return 1;
++    }
++  if (pthread_cond_signal (&c) != 0)
++    {
++      puts ("1st cond_signal failed");
++      return 1;
++    }
++  if (pthread_cancel (th) != 0)
++    {
++      puts ("cancel failed");
++      return 1;
++    }
++  if (pthread_mutex_unlock (&m) != 0)
++    {
++      puts ("1st mutex_unlock failed");
++      return 1;
++    }
++  void *res;
++  if (pthread_join (th, &res) != 0)
++    {
++      puts ("1st join failed");
++      return 1;
++    }
++  if (res != PTHREAD_CANCELED)
++    {
++      puts ("first thread not canceled");
++      status = 1;
++    }
++
++  printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n",
++        c.__data.__lock, c.__data.__futex, c.__data.__total_seq,
++        c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex,
++        c.__data.__nwaiters, c.__data.__broadcast_seq);
++
++  if (pthread_create (&th, NULL, tf, (void *) 1l) != 0)
++    {
++      puts ("2nd create failed");
++      return 1;
++    }
++  e = pthread_barrier_wait (&b);
++  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
++    {
++      puts ("2nd barrier_wait failed");
++      return 1;
++    }
++  if (pthread_mutex_lock (&m) != 0)
++    {
++      puts ("2nd mutex_lock failed");
++      return 1;
++    }
++  if (pthread_cond_signal (&c) != 0)
++    {
++      puts ("2nd cond_signal failed");
++      return 1;
++    }
++  if (pthread_mutex_unlock (&m) != 0)
++    {
++      puts ("2nd mutex_unlock failed");
++      return 1;
++    }
++  if (pthread_join (th, &res) != 0)
++    {
++      puts ("2nd join failed");
++      return 1;
++    }
++  if (res != NULL)
++    {
++      puts ("2nd thread canceled");
++      status = 1;
++    }
++
++  printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n",
++        c.__data.__lock, c.__data.__futex, c.__data.__total_seq,
++        c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex,
++        c.__data.__nwaiters, c.__data.__broadcast_seq);
++
++  return status;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/nptl/sysdeps/pthread/pthread_cond_wait.c      2 Sep 2004 18:49:34 -0000       1.16
++++ libc/nptl/sysdeps/pthread/pthread_cond_wait.c      9 Sep 2006 11:21:23 -0000       1.18
+@@ -50,10 +50,16 @@ __condvar_cleanup (void *arg)
+   if (cbuffer->bc_seq == cbuffer->cond->__data.__broadcast_seq)
+     {
+       /* This thread is not waiting anymore.  Adjust the sequence counters
+-       appropriately.  */
+-      ++cbuffer->cond->__data.__wakeup_seq;
++       appropriately.  We do not increment WAKEUP_SEQ if this would
++       bump it over the value of TOTAL_SEQ.  This can happen if a thread
++       was woken and then canceled.  */
++      if (cbuffer->cond->__data.__wakeup_seq
++        < cbuffer->cond->__data.__total_seq)
++      {
++        ++cbuffer->cond->__data.__wakeup_seq;
++        ++cbuffer->cond->__data.__futex;
++      }
+       ++cbuffer->cond->__data.__woken_seq;
+-      ++cbuffer->cond->__data.__futex;
+     }
+   cbuffer->cond->__data.__nwaiters -= 1 << COND_CLOCK_BITS;
+--- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S       2 Sep 2004 18:53:10 -0000       1.37
++++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S       9 Sep 2006 11:21:23 -0000       1.39
+@@ -406,12 +406,22 @@ __condvar_tw_cleanup:
+       cmpl    20(%esp), %eax
+       jne     3f
+-      addl    $1, wakeup_seq(%ebx)
+-      adcl    $0, wakeup_seq+4(%ebx)
++      /* We increment the wakeup_seq counter only if it is lower than
++         total_seq.  If this is not the case the thread was woken and
++         then canceled.  In this case we ignore the signal.  */
++      movl    total_seq(%ebx), %eax
++      movl    total_seq+4(%ebx), %edi
++      cmpl    wakeup_seq+4(%ebx), %edi
++      jb      6f
++      ja      7f
++      cmpl    wakeup_seq(%ebx), %eax
++      jbe     7f
++6:    addl    $1, wakeup_seq(%ebx)
++      adcl    $0, wakeup_seq+4(%ebx)
+       addl    $1, cond_futex(%ebx)
+-      addl    $1, woken_seq(%ebx)
++7:    addl    $1, woken_seq(%ebx)
+       adcl    $0, woken_seq+4(%ebx)
+ 3:    subl    $(1 << clock_bits), cond_nwaiters(%ebx)
+--- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S    2 Sep 2004 18:52:38 -0000       1.32
++++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S    9 Sep 2006 11:21:23 -0000       1.34
+@@ -297,12 +297,22 @@ __condvar_w_cleanup:
+       cmpl    12(%esp), %eax
+       jne     3f
+-      addl    $1, wakeup_seq(%ebx)
+-      adcl    $0, wakeup_seq+4(%ebx)
++      /* We increment the wakeup_seq counter only if it is lower than
++         total_seq.  If this is not the case the thread was woken and
++         then canceled.  In this case we ignore the signal.  */
++      movl    total_seq(%ebx), %eax
++      movl    total_seq+4(%ebx), %edi
++      cmpl    wakeup_seq+4(%ebx), %edi
++      jb      6f
++      ja      7f
++      cmpl    wakeup_seq(%ebx), %eax
++      jbe     7f
++6:    addl    $1, wakeup_seq(%ebx)
++      adcl    $0, wakeup_seq+4(%ebx)
+       addl    $1, cond_futex(%ebx)
+-      addl    $1, woken_seq(%ebx)
++7:    addl    $1, woken_seq(%ebx)
+       adcl    $0, woken_seq+4(%ebx)
+ 3:    subl    $(1 << clock_bits), cond_nwaiters(%ebx)
+--- libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S       31 Mar 2005 10:00:15 -0000      1.22
++++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S       9 Sep 2006 11:21:23 -0000       1.24
+@@ -67,9 +67,15 @@ __condvar_cleanup:
+       cmpl    4(%r8), %edx
+       jne     3f
++      /* We increment the wakeup_seq counter only if it is lower than
++         total_seq.  If this is not the case the thread was woken and
++         then canceled.  In this case we ignore the signal.  */
++      movq    total_seq(%rdi), %rax
++      cmpq    wakeup_seq(%rdi), %rax
++      jbe     6f
+       incq    wakeup_seq(%rdi)
+-      incq    woken_seq(%rdi)
+       incl    cond_futex(%rdi)
++6:    incq    woken_seq(%rdi)
+ 3:    subl    $(1 << clock_bits), cond_nwaiters(%rdi)
diff --git a/src/patches/glibc/glibc-bz3124.patch b/src/patches/glibc/glibc-bz3124.patch
new file mode 100644 (file)
index 0000000..b6895bd
--- /dev/null
@@ -0,0 +1,241 @@
+2006-09-05  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #3124]
+       * descr.h (struct pthread): Add parent_cancelhandling.
+       * sysdeps/pthread/createthread.c (create_thread): Pass parent
+       cancelhandling value to child.
+       * pthread_create.c (start_thread): If parent thread was canceled
+       reset the SIGCANCEL mask.
+       * Makefile (tests): Add tst-cancel25.
+       * tst-cancel25.c: New file.
+
+--- libc/nptl/Makefile 21 Aug 2006 21:02:10 -0000      1.186
++++ libc/nptl/Makefile 8 Sep 2006 10:40:49 -0000       1.188
+@@ -220,7 +220,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 \
+       tst-cancel6 tst-cancel7 tst-cancel8 tst-cancel9 tst-cancel10 \
+       tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \
+       tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 tst-cancel20 \
+-      tst-cancel21 tst-cancel22 tst-cancel23 \
++      tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel25 \
+       tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \
+       tst-flock1 tst-flock2 \
+       tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \
+--- libc/nptl/descr.h  14 Aug 2006 22:58:59 -0000      1.36
++++ libc/nptl/descr.h  5 Sep 2006 17:14:03 -0000       1.37
+@@ -296,6 +296,10 @@ struct pthread
+   /* True if thread must stop at startup time.  */
+   bool stopped_start;
++  /* The parent's cancel handling at the time of the pthread_create
++     call.  This might be needed to undo the effects of a cancellation.  */
++  int parent_cancelhandling;
++
+   /* Lock to synchronize access to the descriptor.  */
+   lll_lock_t lock;
+--- libc/nptl/pthread_create.c 14 Aug 2006 23:06:09 -0000      1.53
++++ libc/nptl/pthread_create.c 5 Sep 2006 17:12:15 -0000       1.54
+@@ -251,6 +251,19 @@ start_thread (void *arg)
+     }
+ #endif
++  /* If the parent was running cancellation handlers while creating
++     the thread the new thread inherited the signal mask.  Reset the
++     cancellation signal mask.  */
++  if (__builtin_expect (pd->parent_cancelhandling & CANCELING_BITMASK, 0))
++    {
++      INTERNAL_SYSCALL_DECL (err);
++      sigset_t mask;
++      __sigemptyset (&mask);
++      __sigaddset (&mask, SIGCANCEL);
++      (void) INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_UNBLOCK, &mask,
++                             NULL, _NSIG / 8);
++    }
++
+   /* This is where the try/finally block should be created.  For
+      compilers without that support we do use setjmp.  */
+   struct pthread_unwind_buf unwind_buf;
+--- libc/nptl/tst-cancel25.c   1 Jan 1970 00:00:00 -0000
++++ libc/nptl/tst-cancel25.c   5 Sep 2006 17:11:13 -0000       1.1
+@@ -0,0 +1,171 @@
++#include <pthreadP.h>
++#include <signal.h>
++#include <stdio.h>
++#include <stdlib.h>
++
++
++static pthread_barrier_t b;
++static pthread_t th2;
++
++
++static void *
++tf2 (void *arg)
++{
++  sigset_t mask;
++  if (pthread_sigmask (SIG_SETMASK, NULL, &mask) != 0)
++    {
++      puts ("pthread_sigmask failed");
++      exit (1);
++    }
++  if (sigismember (&mask, SIGCANCEL))
++    {
++      puts ("SIGCANCEL blocked in new thread");
++      exit (1);
++    }
++
++  /* Sync with the main thread so that we do not test anything else.  */
++  int e = pthread_barrier_wait (&b);
++  if (e != 0  && e != PTHREAD_BARRIER_SERIAL_THREAD)
++    {
++      puts ("barrier_wait failed");
++      exit (1);
++    }
++
++  while (1)
++    {
++      /* Just a cancelable call.  */
++      struct timespec ts = { 10000, 0 };
++      nanosleep (&ts, 0);
++    }
++
++  return NULL;
++}
++
++
++static void
++unwhand (void *arg)
++{
++  if (pthread_create (&th2, NULL, tf2, NULL) != 0)
++    {
++      puts ("unwhand: create failed");
++      exit (1);
++    }
++}
++
++
++static void *
++tf (void *arg)
++{
++  pthread_cleanup_push (unwhand, NULL);
++
++  /* Sync with the main thread so that we do not test anything else.  */
++  int e = pthread_barrier_wait (&b);
++  if (e != 0  && e != PTHREAD_BARRIER_SERIAL_THREAD)
++    {
++      puts ("barrier_wait failed");
++      exit (1);
++    }
++
++  while (1)
++    {
++      /* Just a cancelable call.  */
++      struct timespec ts = { 10000, 0 };
++      nanosleep (&ts, 0);
++    }
++
++  pthread_cleanup_pop (0);
++
++  return NULL;
++}
++
++
++static int
++do_test (void)
++{
++  if (pthread_barrier_init (&b, NULL, 2) != 0)
++    {
++      puts ("barrier_init failed");
++      return 1;
++    }
++
++  pthread_t th1;
++  if (pthread_create (&th1, NULL, tf, NULL) != 0)
++    {
++      puts ("create failed");
++      return 1;
++    }
++
++  int e = pthread_barrier_wait (&b);
++  if (e != 0  && e != PTHREAD_BARRIER_SERIAL_THREAD)
++    {
++      puts ("barrier_wait failed");
++      return 1;
++    }
++
++  /* Make sure tf1 enters nanosleep.  */
++  struct timespec ts = { 0, 500000000 };
++  while (nanosleep (&ts, &ts) != 0)
++    ;
++
++  if (pthread_cancel (th1) != 0)
++    {
++      puts ("1st cancel failed");
++      return 1;
++    }
++
++  void *res;
++  if (pthread_join (th1, &res) != 0)
++    {
++      puts ("1st join failed");
++      return 1;
++    }
++  if (res != PTHREAD_CANCELED)
++    {
++      puts ("1st thread not canceled");
++      return 1;
++    }
++
++  e = pthread_barrier_wait (&b);
++  if (e != 0  && e != PTHREAD_BARRIER_SERIAL_THREAD)
++    {
++      puts ("barrier_wait failed");
++      return 1;
++    }
++
++  /* Make sure tf2 enters nanosleep.  */
++  ts.tv_sec = 0;
++  ts.tv_nsec = 500000000;
++  while (nanosleep (&ts, &ts) != 0)
++    ;
++
++  puts ("calling pthread_cancel the second time");
++  if (pthread_cancel (th2) != 0)
++    {
++      puts ("2nd cancel failed");
++      return 1;
++    }
++
++  puts ("calling pthread_join the second time");
++  if (pthread_join (th2, &res) != 0)
++    {
++      puts ("2nd join failed");
++      return 1;
++    }
++  if (res != PTHREAD_CANCELED)
++    {
++      puts ("2nd thread not canceled");
++      return 1;
++    }
++
++  if (pthread_barrier_destroy (&b) != 0)
++    {
++      puts ("barrier_destroy failed");
++      return 0;
++    }
++
++  return 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#define TIMEOUT 4
++#include "../test-skeleton.c"
+--- libc/nptl/sysdeps/pthread/createthread.c   20 Nov 2004 07:12:45 -0000      1.27
++++ libc/nptl/sysdeps/pthread/createthread.c   5 Sep 2006 17:13:14 -0000       1.28
+@@ -242,6 +242,7 @@ create_thread (struct pthread *pd, const
+                      || (attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0))
+     stopped = true;
+   pd->stopped_start = stopped;
++  pd->parent_cancelhandling = THREAD_GETMEM (THREAD_SELF, cancelhandling);
+   /* Actually create the thread.  */
+   int res = do_clone (pd, attr, clone_flags, start_thread,
diff --git a/src/patches/glibc/glibc-bz3155.patch b/src/patches/glibc/glibc-bz3155.patch
new file mode 100644 (file)
index 0000000..4fd9089
--- /dev/null
@@ -0,0 +1,27 @@
+2006-09-07  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #3155]
+       * sysdeps/powerpc/powerpc32/fpu/s_lrint.S (__lrint): Don't access
+       stack below r1.
+
+--- libc/sysdeps/powerpc/powerpc32/fpu/s_lrint.S       28 Jan 2006 00:07:39 -0000      1.2
++++ libc/sysdeps/powerpc/powerpc32/fpu/s_lrint.S       7 Sep 2006 13:46:45 -0000       1.3
+@@ -21,13 +21,15 @@
+ #include <math_ldbl_opt.h>
+ /* long int[r3] __lrint (double x[fp1])  */
+-ENTRY (__lrint)       
++ENTRY (__lrint)
++      stwu    r1,-16(r1)
+       fctiw   fp13,fp1
+-      stfd    fp13,-8(r1)
++      stfd    fp13,8(r1)
+       nop     /* Insure the following load is in a different dispatch group */
+       nop     /* to avoid pipe stall on POWER4&5.  */
+       nop
+-      lwz     r3,-4(r1)       
++      lwz     r3,12(r1)
++      addi    r1,r1,16
+       blr
+       END (__lrint)
diff --git a/src/patches/glibc/glibc-bz3253.patch b/src/patches/glibc/glibc-bz3253.patch
new file mode 100644 (file)
index 0000000..e470a27
--- /dev/null
@@ -0,0 +1,271 @@
+2006-09-30  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/generic/glob.c (glob_in_dir): Add some comments and asserts to
+       explain why there are no leaks.
+
+2006-09-25  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #3253]
+       * sysdeps/generic/glob.c (glob_in_dir): Don't alloca one struct globlink at a
+       time, rather allocate increasingly bigger arrays of pointers, if
+       possible with alloca, if too large with malloc.
+
+--- libc/sysdeps/generic/glob.c        11 Jan 2006 05:30:02 -0000      1.69
++++ libc/sysdeps/generic/glob.c        30 Sep 2006 15:08:44 -0000      1.72
+@@ -1316,16 +1316,25 @@ glob_in_dir (pattern, directory, flags, 
+ {
+   size_t dirlen = strlen (directory);
+   __ptr_t stream = NULL;
+-  struct globlink
++  struct globnames
+     {
+-      struct globlink *next;
+-      char *name;
++      struct globnames *next;
++      size_t count;
++      char *name[64];
+     };
+-  struct globlink *names = NULL;
+-  size_t nfound;
++#define INITIAL_COUNT sizeof (init_names.name) / sizeof (init_names.name[0])
++  struct globnames init_names;
++  struct globnames *names = &init_names;
++  struct globnames *names_alloca = &init_names;
++  size_t nfound = 0;
++  size_t allocasize = sizeof (init_names);
++  size_t cur = 0;
+   int meta;
+   int save;
++  init_names.next = NULL;
++  init_names.count = INITIAL_COUNT;
++
+   meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
+   if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
+     {
+@@ -1333,7 +1342,6 @@ glob_in_dir (pattern, directory, flags, 
+        characters and we must not return an error therefore the
+        result will always contain exactly one name.  */
+       flags |= GLOB_NOCHECK;
+-      nfound = 0;
+     }
+   else if (meta == 0 &&
+          ((flags & GLOB_NOESCAPE) || strchr (pattern, '\\') == NULL))
+@@ -1362,8 +1370,6 @@ glob_in_dir (pattern, directory, flags, 
+       /* We found this file to be existing.  Now tell the rest
+          of the function to copy this name into the result.  */
+       flags |= GLOB_NOCHECK;
+-
+-      nfound = 0;
+     }
+   else
+     {
+@@ -1371,12 +1377,10 @@ glob_in_dir (pattern, directory, flags, 
+       {
+         /* This is a special case for matching directories like in
+            "*a/".  */
+-        names = (struct globlink *) __alloca (sizeof (struct globlink));
+-        names->name = (char *) malloc (1);
+-        if (names->name == NULL)
++        names->name[cur] = (char *) malloc (1);
++        if (names->name[cur] == NULL)
+           goto memory_error;
+-        names->name[0] = '\0';
+-        names->next = NULL;
++        *names->name[cur++] = '\0';
+         nfound = 1;
+         meta = 0;
+       }
+@@ -1391,7 +1395,6 @@ glob_in_dir (pattern, directory, flags, 
+                 && ((errfunc != NULL && (*errfunc) (directory, errno))
+                     || (flags & GLOB_ERR)))
+               return GLOB_ABORTED;
+-            nfound = 0;
+             meta = 0;
+           }
+         else
+@@ -1402,7 +1405,6 @@ glob_in_dir (pattern, directory, flags, 
+                              | FNM_CASEFOLD
+ #endif
+                              );
+-            nfound = 0;
+             flags |= GLOB_MAGCHAR;
+             while (1)
+@@ -1466,21 +1468,35 @@ glob_in_dir (pattern, directory, flags, 
+                         link_exists_p (directory, dirlen, name, pglob,
+                                        flags))
+                       {
+-                        struct globlink *new = (struct globlink *)
+-                          __alloca (sizeof (struct globlink));
++                        if (cur == names->count)
++                          {
++                            struct globnames *newnames;
++                            size_t count = names->count * 2;
++                            size_t size = (sizeof (struct globnames)
++                                           + ((count - INITIAL_COUNT)
++                                              * sizeof (char *)));
++                            allocasize += size;
++                            if (__libc_use_alloca (allocasize))
++                              newnames = names_alloca = __alloca (size);
++                            else if ((newnames = malloc (size))
++                                     == NULL)
++                              goto memory_error;
++                            newnames->count = count;
++                            newnames->next = names;
++                            names = newnames;
++                            cur = 0;
++                          }
+                         len = NAMLEN (d);
+-                        new->name = (char *) malloc (len + 1);
+-                        if (new->name == NULL)
++                        names->name[cur] = (char *) malloc (len + 1);
++                        if (names->name[cur] == NULL)
+                           goto memory_error;
+ #ifdef HAVE_MEMPCPY
+-                        *((char *) mempcpy ((__ptr_t) new->name, name, len))
++                        *((char *) mempcpy (names->name[cur++], name, len))
+                           = '\0';
+ #else
+-                        memcpy ((__ptr_t) new->name, name, len);
+-                        new->name[len] = '\0';
++                        memcpy ((__ptr_t) names->name[cur], name, len);
++                        names->name[cur++][len] = '\0';
+ #endif
+-                        new->next = names;
+-                        names = new;
+                         ++nfound;
+                       }
+                   }
+@@ -1493,66 +1509,97 @@ glob_in_dir (pattern, directory, flags, 
+     {
+       size_t len = strlen (pattern);
+       nfound = 1;
+-      names = (struct globlink *) __alloca (sizeof (struct globlink));
+-      names->next = NULL;
+-      names->name = (char *) malloc (len + 1);
+-      if (names->name == NULL)
++      names->name[cur] = (char *) malloc (len + 1);
++      if (names->name[cur] == NULL)
+       goto memory_error;
+ #ifdef HAVE_MEMPCPY
+-      *((char *) mempcpy (names->name, pattern, len)) = '\0';
++      *((char *) mempcpy (names->name[cur++], pattern, len)) = '\0';
+ #else
+-      memcpy (names->name, pattern, len);
+-      names->name[len] = '\0';
++      memcpy (names->name[cur], pattern, len);
++      names->name[cur++][len] = '\0';
+ #endif
+     }
++  int result = GLOB_NOMATCH;
+   if (nfound != 0)
+     {
+-      char **new_gl_pathv;
++      result = 0;
++      char **new_gl_pathv;
+       new_gl_pathv
+       = (char **) realloc (pglob->gl_pathv,
+                            (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
+                            * sizeof (char *));
+       if (new_gl_pathv == NULL)
+-      goto memory_error;
+-      pglob->gl_pathv = new_gl_pathv;
++      {
++      memory_error:
++        while (1)
++          {
++            struct globnames *old = names;
++            for (size_t i = 0; i < cur; ++i)
++              free (names->name[i]);
++            names = names->next;
++            /* NB: we will not leak memory here if we exit without
++               freeing the current block assigned to OLD.  At least
++               the very first block is always allocated on the stack
++               and this is the block assigned to OLD here.  */
++            if (names == NULL)
++              {
++                assert (old == &init_names);
++                break;
++              }
++            cur = names->count;
++            if (old == names_alloca)
++              names_alloca = names;
++            else
++              free (old);
++          }
++        result = GLOB_NOSPACE;
++      }
++      else
++      {
++        while (1)
++          {
++            struct globnames *old = names;
++            for (size_t i = 0; i < cur; ++i)
++              new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++]
++                = names->name[i];
++            names = names->next;
++            /* NB: we will not leak memory here if we exit without
++               freeing the current block assigned to OLD.  At least
++               the very first block is always allocated on the stack
++               and this is the block assigned to OLD here.  */
++            if (names == NULL)
++              {
++                assert (old == &init_names);
++                break;
++              }
++            cur = names->count;
++            if (old == names_alloca)
++              names_alloca = names;
++            else
++              free (old);
++          }
+-      for (; names != NULL; names = names->next)
+-      pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc++] = names->name;
+-      pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
++        pglob->gl_pathv = new_gl_pathv;
+-      pglob->gl_flags = flags;
++        pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
++
++        pglob->gl_flags = flags;
++      }
+     }
+-  save = errno;
+   if (stream != NULL)
+     {
++      save = errno;
+       if (flags & GLOB_ALTDIRFUNC)
+       (*pglob->gl_closedir) (stream);
+       else
+       closedir ((DIR *) stream);
++      __set_errno (save);
+     }
+-  __set_errno (save);
+-  return nfound == 0 ? GLOB_NOMATCH : 0;
+-
+- memory_error:
+-  {
+-    int save = errno;
+-    if (flags & GLOB_ALTDIRFUNC)
+-      (*pglob->gl_closedir) (stream);
+-    else
+-      closedir ((DIR *) stream);
+-    __set_errno (save);
+-  }
+-  while (names != NULL)
+-    {
+-      if (names->name != NULL)
+-      free ((__ptr_t) names->name);
+-      names = names->next;
+-    }
+-  return GLOB_NOSPACE;
++  return result;
+ }
+ #endif        /* Not ELIDE_CODE.  */
diff --git a/src/patches/glibc/glibc-bz3406.patch b/src/patches/glibc/glibc-bz3406.patch
new file mode 100644 (file)
index 0000000..3a9b433
--- /dev/null
@@ -0,0 +1,27 @@
+2008-02-11  Joseph Myers  <joseph@codesourcery.com>
+
+       [BZ #3406]
+       * sysdeps/ieee754/flt-32/w_expf.c (o_threshold): Correct value.
+       * math/libm-test.inc (exp_test): Test 88.72269439697265625.
+
+--- libc/math/libm-test.inc    11 Apr 2008 19:32:30 -0000      1.79
++++ libc/math/libm-test.inc    22 May 2008 19:59:10 -0000      1.81
+@@ -2510,6 +2510,7 @@ exp_test (void)
+   TEST_f_f (exp, 3, M_E3l);
+   TEST_f_f (exp, 0.75L, 2.11700001661267466854536981983709561L);
+   TEST_f_f (exp, 50.0L, 5184705528587072464087.45332293348538L);
++  TEST_f_f (exp, 88.72269439697265625L, 3.40233126623160774937554134772290447915e38L);
+ #ifdef TEST_LDOUBLE
+   /* The result can only be represented in long double.  */
+   TEST_f_f (exp, 1000.0L, 0.197007111401704699388887935224332313e435L);
+--- libc/sysdeps/ieee754/flt-32/w_expf.c       14 Jul 1999 00:03:46 -0000      1.1
++++ libc/sysdeps/ieee754/flt-32/w_expf.c       11 May 2008 17:49:19 -0000      1.2
+@@ -29,7 +29,7 @@ static const float
+ #else
+ static float
+ #endif
+-o_threshold=  8.8721679688e+01,  /* 0x42b17180 */
++o_threshold=  8.8722831726e+01,  /* 0x42b17217 */
+ u_threshold= -1.0397208405e+02;  /* 0xc2cff1b5 */
+ #ifdef __STDC__
diff --git a/src/patches/glibc/glibc-bz3451.patch b/src/patches/glibc/glibc-bz3451.patch
new file mode 100644 (file)
index 0000000..ab8a672
--- /dev/null
@@ -0,0 +1,62 @@
+2006-11-10  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #3451]
+       * sysdeps/i386/fpu/bits/mathinline.h (floor): Make rounding mode
+       change atomic.
+       (ceil): Likewise.
+
+--- libc/sysdeps/i386/fpu/bits/mathinline.h    7 Sep 2004 22:23:42 -0000       1.58
++++ libc/sysdeps/i386/fpu/bits/mathinline.h    10 Nov 2006 20:42:00 -0000      1.60
+@@ -529,24 +529,38 @@ __inline_mathcodeNP (tanh, __x, \
+ __inline_mathcodeNP (floor, __x, \
+   register long double __value;                                                     \
+-  __volatile unsigned short int __cw;                                       \
+-  __volatile unsigned short int __cwtmp;                                    \
+-  __asm __volatile ("fnstcw %0" : "=m" (__cw));                                     \
+-  __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */                   \
+-  __asm __volatile ("fldcw %0" : : "m" (__cwtmp));                          \
+-  __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));                \
+-  __asm __volatile ("fldcw %0" : : "m" (__cw));                                     \
++  register int __ignore;                                                    \
++  unsigned short int __cw;                                                  \
++  unsigned short int __cwtmp;                                               \
++  __asm __volatile ("fnstcw %3\n\t"                                         \
++                  "movzwl %3, %1\n\t"                                       \
++                  "andl $0xf3ff, %1\n\t"                                    \
++                  "orl $0x0400, %1\n\t"       /* rounding down */           \
++                  "movw %w1, %2\n\t"                                        \
++                  "fldcw %2\n\t"                                            \
++                  "frndint\n\t"                                             \
++                  "fldcw %3"                                                \
++                  : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp),       \
++                    "=m" (__cw)                                             \
++                  : "0" (__x));                                             \
+   return __value)
+ __inline_mathcodeNP (ceil, __x, \
+   register long double __value;                                                     \
+-  __volatile unsigned short int __cw;                                       \
+-  __volatile unsigned short int __cwtmp;                                    \
+-  __asm __volatile ("fnstcw %0" : "=m" (__cw));                                     \
+-  __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */                             \
+-  __asm __volatile ("fldcw %0" : : "m" (__cwtmp));                          \
+-  __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));                \
+-  __asm __volatile ("fldcw %0" : : "m" (__cw));                                     \
++  register int __ignore;                                                    \
++  unsigned short int __cw;                                                  \
++  unsigned short int __cwtmp;                                               \
++  __asm __volatile ("fnstcw %3\n\t"                                         \
++                  "movzwl %3, %1\n\t"                                       \
++                  "andl $0xf3ff, %1\n\t"                                    \
++                  "orl $0x0800, %1\n\t"       /* rounding up */             \
++                  "movw %w1, %2\n\t"                                        \
++                  "fldcw %2\n\t"                                            \
++                  "frndint\n\t"                                             \
++                  "fldcw %3"                                                \
++                  : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp),       \
++                    "=m" (__cw)                                             \
++                  : "0" (__x));                                             \
+   return __value)
+ #ifdef __FAST_MATH__
diff --git a/src/patches/glibc/glibc-bz3458.patch b/src/patches/glibc/glibc-bz3458.patch
new file mode 100644 (file)
index 0000000..fe10bfa
--- /dev/null
@@ -0,0 +1,57 @@
+2007-02-21  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #3458]
+       * sysdeps/unix/sysv/linux/posix_madvise.c: New file.
+       * sysdeps/unix/sysv/linux/syscalls.list: Remove posix_madvise entry.
+
+--- libc/sysdeps/unix/sysv/linux/posix_madvise.c       1 Jan 1970 00:00:00 -0000
++++ libc/sysdeps/unix/sysv/linux/posix_madvise.c       21 Feb 2007 19:07:06 -0000      1.2
+@@ -0,0 +1,38 @@
++/* 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 <sysdep.h>
++#include <sys/mman.h>
++
++
++int
++posix_madvise (void *addr, size_t len, int advice)
++{
++  /* We have one problem: the kernel's MADV_DONTNEED does not
++     correspond to POSIX's POSIX_MADV_DONTNEED.  The former simply
++     discards changes made to the memory without writing it back to
++     disk, if this would be necessary.  The POSIX behavior does not
++     allow this.  There is no functionality mapping the POSIX behavior
++     so far so we ignore that advice for now.  */
++  if (advice == POSIX_MADV_DONTNEED)
++    return 0;
++
++  INTERNAL_SYSCALL_DECL (err);
++  int result = INTERNAL_SYSCALL (madvise, err, 3, addr, len, advice);
++  return INTERNAL_SYSCALL_ERRNO (result, err);
++}
+--- libc/sysdeps/unix/sysv/linux/syscalls.list 11 Oct 2006 20:18:04 -0000      1.128
++++ libc/sysdeps/unix/sysv/linux/syscalls.list 21 Feb 2007 19:02:17 -0000      1.129
+@@ -32,7 +32,6 @@ ioperm               -       ioperm          i:iii   ioperm
+ iopl          -       iopl            i:i     iopl
+ klogctl               EXTRA   syslog          i:isi   klogctl
+ lchown                -       lchown          i:sii   __lchown        lchown
+-posix_madvise -       madvise         Vi:pii  posix_madvise
+ madvise               -       madvise         i:pii   madvise
+ mincore               -       mincore         i:anV   mincore
+ mlock         -       mlock           i:bn    mlock
diff --git a/src/patches/glibc/glibc-bz3842.patch b/src/patches/glibc/glibc-bz3842.patch
new file mode 100644 (file)
index 0000000..19dcce7
--- /dev/null
@@ -0,0 +1,30 @@
+2007-02-17  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #3842]
+       * sysdeps/posix/euidaccess.c [_LIBC] (euidaccess): Remove shortcut
+       using __libc_enable_secure.
+
+--- libc/sysdeps/posix/euidaccess.c    6 Jan 2006 11:21:57 -0000       1.13
++++ libc/sysdeps/posix/euidaccess.c    17 Feb 2007 18:12:29 -0000      1.14
+@@ -128,10 +128,6 @@ euidaccess (path, mode)
+ #ifdef        _LIBC
+   uid_t euid;
+   gid_t egid;
+-
+-  if (! __libc_enable_secure)
+-    /* If we are not set-uid or set-gid, access does the same.  */
+-    return __access (path, mode);
+ #else
+   if (have_ids == 0)
+     {
+@@ -162,6 +158,10 @@ euidaccess (path, mode)
+   /* Now we need the IDs.  */
+   euid = __geteuid ();
+   egid = __getegid ();
++
++  if (__getuid () == euid && __getgid () == egid)
++    /* If we are not set-uid or set-gid, access does the same.  */
++    return __access (path, mode);
+ #endif
+   /* The super-user can read and write any file, and execute any file
diff --git a/src/patches/glibc/glibc-bz3855.patch b/src/patches/glibc/glibc-bz3855.patch
new file mode 100644 (file)
index 0000000..f0c541a
--- /dev/null
@@ -0,0 +1,204 @@
+2007-01-11  Jakub Jelinek  <jakub@redhat.com>
+
+       * stdlib/strtod_l.c (____STRTOF_INTERNAL): Fix handling of multi-byte
+       thousands separators.
+       * stdlib/Makefile: Add rules to build and run tst-strtod4.
+       * stdlib/tst-strtod4.c: New test.
+
+       [BZ #3855]
+       * stdlib/strtod_l.c (____STRTOF_INTERNAL): 0x. not followed by
+       hexadecimal digit should accept just the initial 0.
+       * stdlib/tst-strtod2.c (tests): New variable.
+       (do_test): Run several tests rather than just one.
+
+2007-01-03  Ulrich Drepper  <drepper@redhat.com>
+
+       * stdlib/Makefile (tst-strtod3-ENV): Define.
+
+--- libc/stdlib/Makefile       3 Jan 2007 22:42:33 -0000       1.116
++++ libc/stdlib/Makefile       11 Jan 2007 17:37:12 -0000      1.117
+@@ -64,7 +64,7 @@ tests                := tst-strtol tst-strtod testmb t
+                  tst-xpg-basename tst-random tst-random2 tst-bsearch      \
+                  tst-limits tst-rand48 bug-strtod tst-setcontext          \
+                  test-a64l tst-qsort tst-system testmb2 bug-strtod2       \
+-                 tst-atof1 tst-atof2 tst-strtod2 tst-strtod3
++                 tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-strtod4
+ include ../Makeconfig
+@@ -114,6 +114,8 @@ include ../Rules
+ test-canon-ARGS = --test-dir=${common-objpfx}stdlib
+ tst-strtod-ENV = LOCPATH=$(common-objpfx)localedata
++tst-strtod3-ENV = LOCPATH=$(common-objpfx)localedata
++tst-strtod4-ENV = LOCPATH=$(common-objpfx)localedata
+ testmb2-ENV = LOCPATH=$(common-objpfx)localedata
+ # Run a test on the header files we use.
+--- libc/stdlib/strtod_l.c     11 Dec 2006 21:43:48 -0000      1.19
++++ libc/stdlib/strtod_l.c     11 Jan 2007 17:35:29 -0000      1.21
+@@ -650,10 +651,11 @@ ____STRTOF_INTERNAL (nptr, endptr, group
+         if (c != '0')
+           {
+             for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
+-              if (c != thousands[cnt])
++              if (thousands[cnt] != cp[cnt])
+                 break;
+             if (thousands[cnt] != '\0')
+               break;
++            cp += cnt - 1;
+           }
+         c = *++cp;
+       }
+@@ -665,14 +667,23 @@ ____STRTOF_INTERNAL (nptr, endptr, group
+   if (!((c >= L_('0') && c <= L_('9'))
+       || (base == 16 && ((CHAR_TYPE) TOLOWER (c) >= L_('a')
+                          && (CHAR_TYPE) TOLOWER (c) <= L_('f')))
++      || (
+ #ifdef USE_WIDE_CHAR
+-      || c == (wint_t) decimal
++          c == (wint_t) decimal
+ #else
+-      || ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
+-            if (decimal[cnt] != cp[cnt])
+-              break;
+-            decimal[cnt] == '\0'; })
+-#endif
++          ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
++               if (decimal[cnt] != cp[cnt])
++                 break;
++             decimal[cnt] == '\0'; })
++#endif
++          /* '0x.' alone is not a valid hexadecimal number.
++             '.' alone is not valid either, but that has been checked
++             already earlier.  */
++          && (base != 16
++              || cp != start_of_digits
++              || (cp[decimal_len] >= L_('0') && cp[decimal_len] <= L_('9'))
++              || ((CHAR_TYPE) TOLOWER (cp[decimal_len]) >= L_('a')
++                  && (CHAR_TYPE) TOLOWER (cp[decimal_len]) <= L_('f'))))
+       || (base == 16 && (cp != start_of_digits
+                          && (CHAR_TYPE) TOLOWER (c) == L_('p')))
+       || (base != 16 && (CHAR_TYPE) TOLOWER (c) == L_('e'))))
+@@ -715,6 +726,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group
+                 break;
+             if (thousands[cnt] != '\0')
+               break;
++            cp += cnt - 1;
+           }
+ #endif
+       }
+--- libc/stdlib/tst-strtod2.c  11 Dec 2006 21:36:30 -0000      1.2
++++ libc/stdlib/tst-strtod2.c  11 Jan 2007 17:27:16 -0000      1.3
+@@ -1,22 +1,41 @@
+ #include <stdio.h>
+ #include <stdlib.h>
++struct test
++{
++  const char *str;
++  double result;
++  size_t offset;
++} tests[] =
++{
++  { "0xy", 0.0, 1 },
++  { "0x.y", 0.0, 1 },
++  { "0x0.y", 0.0, 4 },
++  { "0x.0y", 0.0, 4 },
++  { ".y", 0.0, 0 },
++  { "0.y", 0.0, 2 },
++  { ".0y", 0.0, 2 }
++};
++
+ static int
+ do_test (void)
+ {
+   int status = 0;
+-  const char s[] = "0x";
+-  char *ep;
+-  double r = strtod (s, &ep);
+-  if (r != 0)
+-    {
+-      printf ("r = %g, expect 0\n", r);
+-      status = 1;
+-    }
+-  if (ep != s + 1)
++  for (size_t i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
+     {
+-      printf ("strtod parsed %ju characters, expected 1\n", ep - s);
+-      status = 1;
++      char *ep;
++      double r = strtod (tests[i].str, &ep);
++      if (r != tests[i].result)
++      {
++        printf ("test %zu r = %g, expect %g\n", i, r, tests[i].result);
++        status = 1;
++      }
++      if (ep != tests[i].str + tests[i].offset)
++      {
++        printf ("test %zu strtod parsed %ju characters, expected %zu\n",
++                i, ep - tests[i].str, tests[i].offset);
++        status = 1;
++      }
+     }
+   return status;
+ }
+--- libc/stdlib/tst-strtod4.c  1 Jan 1970 00:00:00 -0000
++++ libc/stdlib/tst-strtod4.c  11 Jan 2007 17:36:58 -0000      1.1
+@@ -0,0 +1,56 @@
++#include <locale.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#define NBSP "\xc2\xa0"
++
++static const struct
++{
++  const char *in;
++  const char *out;
++  double expected;
++} tests[] =
++  {
++    { "000"NBSP"000"NBSP"000", "", 0.0 },
++    { "1"NBSP"000"NBSP"000,5x", "x", 1000000.5 }
++  };
++#define NTESTS (sizeof (tests) / sizeof (tests[0]))
++
++
++static int
++do_test (void)
++{
++  if (setlocale (LC_ALL, "cs_CZ.UTF-8") == NULL)
++    {
++      puts ("could not set locale");
++      return 1;
++    }
++
++  int status = 0;
++
++  for (int i = 0; i < NTESTS; ++i)
++    {
++      char *ep;
++      double r = __strtod_internal (tests[i].in, &ep, 1);
++
++      if (strcmp (ep, tests[i].out) != 0)
++      {
++        printf ("%d: got rest string \"%s\", expected \"%s\"\n",
++                i, ep, tests[i].out);
++        status = 1;
++      }
++
++      if (r != tests[i].expected)
++      {
++        printf ("%d: got wrong results %g, expected %g\n",
++                i, r, tests[i].expected);
++        status = 1;
++      }
++    }
++
++  return status;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-bz3902.patch b/src/patches/glibc/glibc-bz3902.patch
new file mode 100644 (file)
index 0000000..f6ac97d
--- /dev/null
@@ -0,0 +1,71 @@
+2007-01-22  Ulrich Drepper  <drepper@redhat.com>
+
+       [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.
+
+--- libc/stdio-common/_itoa.c  6 Jun 2004 06:02:14 -0000       1.21
++++ libc/stdio-common/_itoa.c  22 Jan 2007 16:16:08 -0000      1.22
+@@ -269,6 +269,7 @@ _itoa (value, buflim, base, upper_case)
+     default:
+       {
++      char *bufend = buflim;
+ #if BITS_PER_MP_LIMB == 64
+       mp_limb_t base_multiplier = brec->base_multiplier;
+       if (brec->flag)
+@@ -454,6 +455,8 @@ _itoa (value, buflim, base, upper_case)
+         }
+       while (n != 0);
+ #endif
++      if (buflim == bufend)
++        *--buflim = '0';
+       }
+       break;
+     }
+--- libc/stdio-common/Makefile 3 Aug 2006 09:25:01 -0000       1.98
++++ libc/stdio-common/Makefile 22 Jan 2007 16:17:13 -0000      1.99
+@@ -54,7 +54,7 @@ tests := tstscanf test_rdwr test-popen t
+        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
+--- libc/stdio-common/bug17.c  1 Jan 1970 00:00:00 -0000
++++ libc/stdio-common/bug17.c  22 Jan 2007 16:17:04 -0000      1.1
+@@ -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/src/patches/glibc/glibc-bz394.patch b/src/patches/glibc/glibc-bz394.patch
new file mode 100644 (file)
index 0000000..3296ea2
--- /dev/null
@@ -0,0 +1,40 @@
+2005-09-23  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #394]
+       * libio/fmemopen.c (fmemopen_write): Return 0 instead of -1 if
+       nothing can be written.
+       * libio/iofopncook.c (_IO_cookie_write): If something went wrong,
+       set error bit.
+
+--- libc/libio/iofopncook.c    19 Jan 2005 19:25:42 -0000      1.23
++++ libc/libio/iofopncook.c    23 Sep 2005 16:35:17 -0000      1.24
+@@ -64,9 +64,16 @@ _IO_cookie_write (fp, buf, size)
+   struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
+   if (cfile->__io_functions.write == NULL)
+-    return -1;
++    {
++      fp->_flags |= _IO_ERR_SEEN;
++      return 0;
++    }
++
++  _IO_ssize_t n = cfile->__io_functions.write (cfile->__cookie, buf, size);
++  if (n < size)
++    fp->_flags |= _IO_ERR_SEEN;
+-  return cfile->__io_functions.write (cfile->__cookie, buf, size);
++  return n;
+ }
+ static _IO_off64_t
+--- libc/libio/fmemopen.c      2 Feb 2005 19:43:54 -0000       1.11
++++ libc/libio/fmemopen.c      23 Sep 2005 16:34:35 -0000      1.12
+@@ -127,7 +127,7 @@ fmemopen_write (void *cookie, const char
+       if ((size_t) (c->pos + addnullc) == c->size)
+       {
+         __set_errno (ENOSPC);
+-        return -1;
++        return 0;
+       }
+       s = c->size - c->pos - addnullc;
+     }
diff --git a/src/patches/glibc/glibc-bz3944.patch b/src/patches/glibc/glibc-bz3944.patch
new file mode 100644 (file)
index 0000000..5d6588b
--- /dev/null
@@ -0,0 +1,109 @@
+2007-02-08  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #3944]
+       * time/strptime_l.c (__strptime_internal): Set have_mon for
+       %b/%B/%h.  Set have_mon and have_mday if tm_mon and tm_mday
+       have been computed from tm_yday and tm_year.  Don't crash
+       in day_of_the_week or day_of_the_year if not have_mon
+       and tm_mon contains bogus value.
+       * time/Makefile (tests): Add tst-strptime3.
+       * time/tst-strptime3.c: New test.
+
+--- libc/time/strptime_l.c     27 Apr 2005 04:30:10 -0000      1.7
++++ libc/time/strptime_l.c     9 Feb 2007 01:32:17 -0000       1.8
+@@ -400,6 +400,7 @@ __strptime_internal (rp, fmt, tm, decide
+           /* Does not match a month name.  */
+           return NULL;
+         tm->tm_mon = cnt;
++        have_mon = 1;
+         want_xday = 1;
+         break;
+       case 'c':
+@@ -1085,11 +1086,15 @@ __strptime_internal (rp, fmt, tm, decide
+             tm->tm_mday =
+               (tm->tm_yday
+                - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1);
++        have_mon = 1;
++        have_mday = 1;
+       }
+-      day_of_the_week (tm);
++      /* Don't crash in day_of_the_week if tm_mon is uninitialized.  */
++      if (have_mon || (unsigned) tm->tm_mon <= 11)
++      day_of_the_week (tm);
+     }
+-  if (want_xday && !have_yday)
++  if (want_xday && !have_yday && (have_mon || (unsigned) tm->tm_mon <= 11))
+     day_of_the_year (tm);
+   if ((have_uweek || have_wweek) && have_wday)
+--- libc/time/Makefile 9 Sep 2006 16:54:49 -0000       1.110
++++ libc/time/Makefile 9 Feb 2007 01:33:54 -0000       1.111
+@@ -35,7 +35,8 @@ distribute := datemsk
+ tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
+          tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \
+-         tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1
++         tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1 \
++         tst-strptime3
+ include ../Rules
+--- libc/time/tst-strptime3.c  1 Jan 1970 00:00:00 -0000
++++ libc/time/tst-strptime3.c  9 Feb 2007 01:33:40 -0000       1.1
+@@ -0,0 +1,55 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <time.h>
++
++
++int
++main (void)
++{
++  int result = 0;
++  struct tm tm;
++
++  memset (&tm, 0xaa, sizeof (tm));
++
++  /* Test we don't crash on uninitialized struct tm.
++     Some fields might contain bogus values until everything
++     needed is initialized, but we shouldn't crash.  */
++  if (strptime ("2007", "%Y", &tm) == NULL
++      || strptime ("12", "%d", &tm) == NULL
++      || strptime ("Feb", "%b", &tm) == NULL
++      || strptime ("13", "%M", &tm) == NULL
++      || strptime ("21", "%S", &tm) == NULL
++      || strptime ("16", "%H", &tm) == NULL)
++    {
++      puts ("strptimes failed");
++      result = 1;
++    }
++
++  if (tm.tm_sec != 21 || tm.tm_min != 13 || tm.tm_hour != 16
++      || tm.tm_mday != 12 || tm.tm_mon != 1 || tm.tm_year != 107
++      || tm.tm_wday != 1 || tm.tm_yday != 42)
++    {
++      puts ("unexpected tm content");
++      result = 1;
++    }
++
++  if (strptime ("8", "%d", &tm) == NULL)
++    {
++      puts ("strptime failed");
++      result = 1;
++    }
++
++  if (tm.tm_sec != 21 || tm.tm_min != 13 || tm.tm_hour != 16
++      || tm.tm_mday != 8 || tm.tm_mon != 1 || tm.tm_year != 107
++      || tm.tm_wday != 4 || tm.tm_yday != 38)
++    {
++      puts ("unexpected tm content");
++      result = 1;
++    }
++
++  if (result == 0)
++    puts ("all OK");
++
++  return 0;
++}
diff --git a/src/patches/glibc/glibc-bz3957.patch b/src/patches/glibc/glibc-bz3957.patch
new file mode 100644 (file)
index 0000000..8e16de1
--- /dev/null
@@ -0,0 +1,189 @@
+2007-02-05  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #3957]
+       * posix/regcomp.c (parse_bracket_exp): Set '\n' bit rather than '\0'
+       bit for RE_HAT_LISTS_NOT_NEWLINE.
+       (build_charclass_op): Remove bogus comment.
+       * posix/Makefile (tests): Add bug-regex27 and bug-regex28.
+       * posix/bug-regex27.c: New test.
+       * posix/bug-regex28.c: New test.
+
+--- libc/posix/regcomp.c       31 Jan 2006 19:17:14 -0000      1.112
++++ libc/posix/regcomp.c       5 Feb 2007 15:23:49 -0000       1.113
+@@ -3019,7 +3019,7 @@ parse_bracket_exp (re_string_t *regexp, 
+ #endif /* not RE_ENABLE_I18N */
+       non_match = 1;
+       if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
+-      bitset_set (sbcset, '\0');
++      bitset_set (sbcset, '\n');
+       re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
+       token_len = peek_token_bracket (token, regexp, syntax);
+       if (BE (token->type == END_OF_RE, 0))
+@@ -3549,10 +3549,6 @@ build_charclass_op (re_dfa_t *dfa, RE_TR
+   if (non_match)
+     {
+ #ifdef RE_ENABLE_I18N
+-      /*
+-      if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
+-      bitset_set(cset->sbcset, '\0');
+-      */
+       mbcset->non_match = 1;
+ #endif /* not RE_ENABLE_I18N */
+     }
+--- libc/posix/Makefile        3 Jan 2007 23:02:10 -0000       1.194
++++ libc/posix/Makefile        5 Feb 2007 15:22:40 -0000       1.195
+@@ -81,7 +81,8 @@ tests                := tstgetopt testfnm runtests run
+                  bug-regex13 bug-regex14 bug-regex15 bug-regex16 \
+                  bug-regex17 bug-regex18 bug-regex19 bug-regex20 \
+                  bug-regex21 bug-regex22 bug-regex23 bug-regex24 \
+-                 bug-regex25 bug-regex26 tst-nice tst-nanosleep tst-regex2 \
++                 bug-regex25 bug-regex26 bug-regex27 bug-regex28 \
++                 tst-nice tst-nanosleep tst-regex2 \
+                  transbug tst-rxspencer tst-pcre tst-boost \
+                  bug-ga1 tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \
+                  tst-getaddrinfo2 bug-glob1 bug-glob2 tst-sysconf \
+--- libc/posix/bug-regex27.c   1 Jan 1970 00:00:00 -0000
++++ libc/posix/bug-regex27.c   5 Feb 2007 15:22:27 -0000       1.1
+@@ -0,0 +1,64 @@
++/* Test REG_NEWLINE.
++   Copyright (C) 2007 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Jakub Jelinek <jakub@redhat.com>, 2007.
++
++   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 <regex.h>
++#include <stdio.h>
++#include <string.h>
++
++struct tests
++{
++  const char *regex;
++  const char *string;
++  int cflags;
++  int retval;
++} tests[] = {
++  { "a.b", "a\nb", REG_EXTENDED | REG_NEWLINE, REG_NOMATCH },
++  { "a.b", "a\nb", REG_EXTENDED, 0 },
++  { "a[^x]b", "a\nb", REG_EXTENDED | REG_NEWLINE, REG_NOMATCH },
++  { "a[^x]b", "a\nb", REG_EXTENDED, 0 }
++};
++
++int
++main (void)
++{
++  regex_t r;
++  size_t i;
++  int ret = 0;
++
++  for (i = 0; i < sizeof (tests) / sizeof (tests[i]); ++i)
++    {
++      memset (&r, 0, sizeof (r));
++      if (regcomp (&r, tests[i].regex, tests[i].cflags))
++      {
++        printf ("regcomp %zd failed\n", i);
++        ret = 1;
++        continue;
++      }
++      int rv = regexec (&r, tests[i].string, 0, NULL, 0);
++      if (rv != tests[i].retval)
++      {
++        printf ("regexec %zd unexpected value %d != %d\n",
++                i, rv, tests[i].retval);
++        ret = 1;
++      }
++      regfree (&r);
++    }
++  return ret;
++}
+--- libc/posix/bug-regex28.c   1 Jan 1970 00:00:00 -0000
++++ libc/posix/bug-regex28.c   5 Feb 2007 15:22:27 -0000       1.1
+@@ -0,0 +1,75 @@
++/* Test RE_HAT_LISTS_NOT_NEWLINE and RE_DOT_NEWLINE.
++   Copyright (C) 2007 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Jakub Jelinek <jakub@redhat.com>, 2007.
++
++   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 <regex.h>
++#include <stdio.h>
++#include <string.h>
++
++struct tests
++{
++  const char *regex;
++  const char *string;
++  reg_syntax_t syntax;
++  int retval;
++} tests[] = {
++#define EGREP RE_SYNTAX_EGREP
++#define EGREP_NL (RE_SYNTAX_EGREP | RE_DOT_NEWLINE) & ~RE_HAT_LISTS_NOT_NEWLINE
++  { "a.b", "a\nb", EGREP, -1 },
++  { "a.b", "a\nb", EGREP_NL, 0 },
++  { "a[^x]b", "a\nb", EGREP, -1 },
++  { "a[^x]b", "a\nb", EGREP_NL, 0 },
++  /* While \S and \W are internally handled as [^[:space:]] and [^[:alnum:]_],
++     RE_HAT_LISTS_NOT_NEWLINE did not make any difference, so ensure
++     it doesn't change.  */
++  { "a\\Sb", "a\nb", EGREP, -1 },
++  { "a\\Sb", "a\nb", EGREP_NL, -1 },
++  { "a\\Wb", "a\nb", EGREP, 0 },
++  { "a\\Wb", "a\nb", EGREP_NL, 0 }
++};
++
++int
++main (void)
++{
++  struct re_pattern_buffer r;
++  size_t i;
++  int ret = 0;
++
++  for (i = 0; i < sizeof (tests) / sizeof (tests[i]); ++i)
++    {
++      re_set_syntax (tests[i].syntax);
++      memset (&r, 0, sizeof (r));
++      if (re_compile_pattern (tests[i].regex, strlen (tests[i].regex), &r))
++      {
++        printf ("re_compile_pattern %zd failed\n", i);
++        ret = 1;
++        continue;
++      }
++      size_t len = strlen (tests[i].string);
++      int rv = re_search (&r, tests[i].string, len, 0, len, NULL);
++      if (rv != tests[i].retval)
++      {
++        printf ("re_search %zd unexpected value %d != %d\n",
++                i, rv, tests[i].retval);
++        ret = 1;
++      }
++      regfree (&r);
++    }
++  return ret;
++}
diff --git a/src/patches/glibc/glibc-bz4070.patch b/src/patches/glibc/glibc-bz4070.patch
new file mode 100644 (file)
index 0000000..adc9f79
--- /dev/null
@@ -0,0 +1,207 @@
+2007-04-13  Jakub Jelinek  <jakub@redhat.com>
+
+       * stdio-common/printf_fp.c (___printf_fp): Fix exponent -4
+       special case handling when wcp == wstartp + 1.  Fix a comment typo.
+       * stdio-common/tfformat.c (sprint_doubles): Add a new testcase.
+
+2007-02-21  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #4070]
+       * stdio-common/printf_fp.c (___printf_fp): Handle a few more
+       special cases.
+       * stdio-common/tfformat.c (sprint_doubles): Some more tests.
+
+2007-02-19  Ulrich Drepper  <drepper@redhat.com>
+
+       * stdio-common/printf_fp.c (___printf_fp): Cleanups and minor
+       optimization.
+
+--- libc/stdio-common/printf_fp.c      25 Apr 2006 18:38:30 -0000      1.58
++++ libc/stdio-common/printf_fp.c      16 Apr 2007 23:28:26 -0000      1.62
+@@ -811,12 +811,14 @@ ___printf_fp (FILE *fp,
+     int chars_needed;
+     int expscale;
+     int intdig_max, intdig_no = 0;
+-    int fracdig_min, fracdig_max, fracdig_no = 0;
++    int fracdig_min;
++    int fracdig_max;
+     int dig_max;
+     int significant;
+     int ngroups = 0;
++    char spec = _tolower (info->spec);
+-    if (_tolower (info->spec) == 'e')
++    if (spec == 'e')
+       {
+       type = info->spec;
+       intdig_max = 1;
+@@ -826,7 +828,7 @@ ___printf_fp (FILE *fp,
+       dig_max = INT_MAX;              /* Unlimited.  */
+       significant = 1;                /* Does not matter here.  */
+       }
+-    else if (_tolower (info->spec) == 'f')
++    else if (spec == 'f')
+       {
+       type = 'f';
+       fracdig_min = fracdig_max = info->prec < 0 ? 6 : info->prec;
+@@ -923,7 +925,9 @@ ___printf_fp (FILE *fp,
+       }
+     /* Generate the needed number of fractional digits.        */
+-    while (fracdig_no < fracdig_min
++    int fracdig_no = 0;
++    int added_zeros = 0;
++    while (fracdig_no < fracdig_min + added_zeros
+          || (fracdig_no < fracdig_max && (fracsize > 1 || frac[0] != 0)))
+       {
+       ++fracdig_no;
+@@ -934,7 +938,7 @@ ___printf_fp (FILE *fp,
+         {
+           ++fracdig_max;
+           if (fracdig_min > 0)
+-            ++fracdig_min;
++            ++added_zeros;
+         }
+       }
+@@ -971,11 +975,23 @@ ___printf_fp (FILE *fp,
+         {
+           /* Process fractional digits.  Terminate if not rounded or
+              radix character is reached.  */
++          int removed = 0;
+           while (*--wtp != decimalwc && *wtp == L'9')
+-            *wtp = '0';
++            {
++              *wtp = L'0';
++              ++removed;
++            }
++          if (removed == fracdig_min && added_zeros > 0)
++            --added_zeros;
+           if (*wtp != decimalwc)
+             /* Round up.  */
+             (*wtp)++;
++          else if (__builtin_expect (spec == 'g' && type == 'f' && info->alt,
++                                     0))
++            /* This is a special case: the rounded number is 1.0,
++               the format is 'g' or 'G', and the alternative format
++               is selected.  This means the result must be "1.".  */
++            --added_zeros;
+         }
+       if (fracdig_no == 0 || *wtp == decimalwc)
+@@ -1042,7 +1058,7 @@ ___printf_fp (FILE *fp,
+   do_expo:
+     /* Now remove unnecessary '0' at the end of the string.  */
+-    while (fracdig_no > fracdig_min && *(wcp - 1) == L'0')
++    while (fracdig_no > fracdig_min + added_zeros && *(wcp - 1) == L'0')
+       {
+       --wcp;
+       --fracdig_no;
+@@ -1060,26 +1076,46 @@ ___printf_fp (FILE *fp,
+     /* Write the exponent if it is needed.  */
+     if (type != 'f')
+       {
+-      *wcp++ = (wchar_t) type;
+-      *wcp++ = expsign ? L'-' : L'+';
+-
+-      /* Find the magnitude of the exponent.  */
+-      expscale = 10;
+-      while (expscale <= exponent)
+-        expscale *= 10;
+-
+-      if (exponent < 10)
+-        /* Exponent always has at least two digits.  */
+-        *wcp++ = L'0';
++      if (__builtin_expect (expsign != 0 && exponent == 4 && spec == 'g', 0))
++        {
++          /* This is another special case.  The exponent of the number is
++             really smaller than -4, which requires the 'e'/'E' format.
++             But after rounding the number has an exponent of -4.  */
++          assert (wcp >= wstartp + 1);
++          assert (wstartp[0] == L'1');
++          __wmemcpy (wstartp, L"0.0001", 6);
++          wstartp[1] = decimalwc;
++          if (wcp >= wstartp + 2)
++            {
++              wmemset (wstartp + 6, L'0', wcp - (wstartp + 2));
++              wcp += 4;
++            }
++          else
++            wcp += 5;
++        }
+       else
+-        do
+-          {
+-            expscale /= 10;
+-            *wcp++ = L'0' + (exponent / expscale);
+-            exponent %= expscale;
+-          }
+-        while (expscale > 10);
+-      *wcp++ = L'0' + exponent;
++        {
++          *wcp++ = (wchar_t) type;
++          *wcp++ = expsign ? L'-' : L'+';
++
++          /* Find the magnitude of the exponent.      */
++          expscale = 10;
++          while (expscale <= exponent)
++            expscale *= 10;
++
++          if (exponent < 10)
++            /* Exponent always has at least two digits.  */
++            *wcp++ = L'0';
++          else
++            do
++              {
++                expscale /= 10;
++                *wcp++ = L'0' + (exponent / expscale);
++                exponent %= expscale;
++              }
++            while (expscale > 10);
++          *wcp++ = L'0' + exponent;
++        }
+       }
+     /* Compute number of characters which must be filled with the padding
+--- libc/stdio-common/tfformat.c       11 Mar 2002 21:46:37 -0000      1.7
++++ libc/stdio-common/tfformat.c       16 Apr 2007 23:28:37 -0000      1.9
+@@ -4012,6 +4012,15 @@ sprint_double_type sprint_doubles[] =
+   {__LINE__, 16,                      "0x1.0p+4", "%.1a"},
+   {__LINE__, 16,                      "0x1.00000000000000000000p+4", "%.20a"},
+   {__LINE__, 4444.88888888,           "4445", "%2.F"},
++  {__LINE__, 0.956,                   "1", "%.0g"},
++  {__LINE__, 1.0956,                  "1.", "%#.0g"},
++  {__LINE__, 0.956,                   "1.", "%#.0g"},
++  {__LINE__, 0.0956,                  "0.1", "%#.0g"},
++  {__LINE__, 0.00956,                 "0.01", "%#.0g"},
++  {__LINE__, 0.000956,                        "0.001", "%#.0g"},
++  {__LINE__, 0.000098,                        "0.0001", "%#.0g"},
++  {__LINE__, 0.0000996,                       "0.00010", "%#.2g"},
++  {__LINE__, 9.999999999999999e-05,   "0.0001", "%g"},
+   {0 }
+@@ -4023,13 +4032,8 @@ sprint_double_type sprint_doubles[] =
+ int required_precision = 13;
+-#if defined(__STDC__) || defined(__cplusplus)
+ static int
+ matches (register char *result, register const char *desired)
+-#else
+-int matches(result, desired)
+-     register char *result; register const char *desired;
+-#endif
+ {
+     int digits_seen = 0;
+     for (;; result++, desired++) {
+@@ -4080,7 +4084,7 @@ int main(int argc, char *argv[])
+   /* And one special test.  */
+   {
+-    const char ref[] = "1.7763568394002504646778106689453125e-15";
++    static const char ref[] = "1.7763568394002504646778106689453125e-15";
+     int i;
+     d = 1.0;
+     for (i = 1; i < 50; ++i)
diff --git a/src/patches/glibc/glibc-bz4074.patch b/src/patches/glibc/glibc-bz4074.patch
new file mode 100644 (file)
index 0000000..6909df6
--- /dev/null
@@ -0,0 +1,29 @@
+2007-02-21  Ulrich Drepper  <drepper@redhat.com>
+
+       * nscd/grpcache.c (cache_addgr): In case a record changed on
+       refresh, adjust key_copy.
+
+       [BZ #4074]
+       * nscd/pwdcache.c (cache_addpw): In case a record changed on
+       refresh, adjust key_copy.
+
+--- libc/nscd/grpcache.c       14 Jan 2007 05:09:52 -0000      1.47
++++ libc/nscd/grpcache.c       21 Feb 2007 09:07:54 -0000      1.48
+@@ -279,6 +279,7 @@ cache_addgr (struct database_dyn *db, in
+                 /* Adjust pointers into the memory block.  */
+                 gr_name = (char *) newp + (gr_name - (char *) dataset);
+                 cp = (char *) newp + (cp - (char *) dataset);
++                key_copy = (char *) newp + (key_copy - (char *) dataset);
+                 dataset = memcpy (newp, dataset, total + n);
+                 alloca_used = false;
+--- libc/nscd/pwdcache.c       14 Jan 2007 05:09:52 -0000      1.45
++++ libc/nscd/pwdcache.c       21 Feb 2007 09:05:19 -0000      1.46
+@@ -274,6 +274,7 @@ cache_addpw (struct database_dyn *db, in
+               {
+                 /* Adjust pointer into the memory block.  */
+                 cp = (char *) newp + (cp - (char *) dataset);
++                key_copy = (char *) newp + (key_copy - (char *) dataset);
+                 dataset = memcpy (newp, dataset, total + n);
+                 alloca_used = false;
diff --git a/src/patches/glibc/glibc-bz4101.patch b/src/patches/glibc/glibc-bz4101.patch
new file mode 100644 (file)
index 0000000..5818d68
--- /dev/null
@@ -0,0 +1,148 @@
+2007-03-15  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #4101]
+       * argp/argp-help.c (hol_cluster_cmp): Fix comparisons used to find
+       ancestors with the same depths.
+       Patch by Niels Moeller <nisse@lysator.liu.se>.
+       (filter_doc): Don't crash if argp is NULL.
+       * argp/Makefile (tests): Add tst-argp2.
+       * argp/tst-argp2.c: New test.
+
+--- libc/argp/Makefile 9 May 2006 22:42:24 -0000       1.7
++++ libc/argp/Makefile 15 Mar 2007 20:08:57 -0000      1.8
+@@ -26,7 +26,7 @@ distribute   = argp-fmtstream.h argp-namef
+ routines      = $(addprefix argp-, ba fmtstream fs-xinl help parse pv \
+                                    pvh xinl eexst)
+-tests         = argp-test tst-argp1 bug-argp1
++tests         = argp-test tst-argp1 bug-argp1 tst-argp2
+ CFLAGS-argp-help.c = $(uses-callbacks) -fexceptions
+ CFLAGS-argp-parse.c = $(uses-callbacks)
+--- libc/argp/argp-help.c      10 May 2006 06:28:06 -0000      1.54
++++ libc/argp/argp-help.c      15 Mar 2007 20:08:18 -0000      1.55
+@@ -672,9 +673,9 @@ hol_cluster_cmp (const struct hol_cluste
+ {
+   /* If one cluster is deeper than the other, use its ancestor at the same
+      level, so that finding the common ancestor is straightforward.  */
+-  while (cl1->depth < cl2->depth)
++  while (cl1->depth > cl2->depth)
+     cl1 = cl1->parent;
+-  while (cl2->depth < cl1->depth)
++  while (cl2->depth > cl1->depth)
+     cl2 = cl2->parent;
+   /* Now reduce both clusters to their ancestors at the point where both have
+@@ -987,7 +988,7 @@ static const char *
+ filter_doc (const char *doc, int key, const struct argp *argp,
+           const struct argp_state *state)
+ {
+-  if (argp->help_filter)
++  if (argp && argp->help_filter)
+     /* We must apply a user filter to this output.  */
+     {
+       void *input = __argp_input (argp, state);
+--- libc/argp/tst-argp2.c      1 Jan 1970 00:00:00 -0000
++++ libc/argp/tst-argp2.c      15 Mar 2007 20:08:46 -0000      1.1
+@@ -0,0 +1,101 @@
++/* Copyright (C) 2007 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Jakub Jelinek <jakub@redhat.com>, 2007.
++
++   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 <argp.h>
++
++static const struct argp_option opt1[] =
++  {
++    { "opt1", '1', "NUMBER", 0, "Option 1" },
++    { NULL, 0, NULL, 0, NULL }
++  };
++
++static const struct argp_option opt2[] =
++  {
++    { "opt2", '2', "NUMBER", 0, "Option 2" },
++    { NULL, 0, NULL, 0, NULL }
++  };
++
++static const struct argp_option opt3[] =
++  {
++    { "opt3", '3', "NUMBER", 0, "Option 3" },
++    { NULL, 0, NULL, 0, NULL }
++  };
++
++static const struct argp_option opt4[] =
++  {
++    { "opt4", '4', "NUMBER", 0, "Option 4" },
++    { NULL, 0, NULL, 0, NULL }
++  };
++
++static const struct argp_option opt5[] =
++  {
++    { "opt5", '5', "NUMBER", 0, "Option 5" },
++    { NULL, 0, NULL, 0, NULL }
++  };
++
++static struct argp argp5 =
++  {
++    opt5, NULL, "args doc5", "doc5", NULL, NULL, NULL
++  };
++
++static struct argp argp4 =
++  {
++    opt4, NULL, "args doc4", "doc4", NULL, NULL, NULL
++  };
++
++static struct argp argp3 =
++  {
++    opt3, NULL, "args doc3", "doc3", NULL, NULL, NULL
++  };
++
++static struct argp_child children2[] =
++  {
++    { &argp4, 0, "child3", 3 },
++    { &argp5, 0, "child4", 4 },
++    { NULL, 0, NULL, 0 }
++  };
++
++static struct argp argp2 =
++  {
++    opt2, NULL, "args doc2", "doc2", children2, NULL, NULL
++  };
++
++static struct argp_child children1[] =
++  {
++    { &argp2, 0, "child1", 1 },
++    { &argp3, 0, "child2", 2 },
++    { NULL, 0, NULL, 0 }
++  };
++
++static struct argp argp1 =
++  {
++    opt1, NULL, "args doc1", "doc1", children1, NULL, NULL
++  };
++
++
++static int
++do_test (void)
++{
++  argp_help (&argp1, stdout, ARGP_HELP_LONG, (char *) "tst-argp2");
++  return 0;
++}
++
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-bz4130.patch b/src/patches/glibc/glibc-bz4130.patch
new file mode 100644 (file)
index 0000000..b45112e
--- /dev/null
@@ -0,0 +1,32 @@
+2007-03-15  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #4130]
+       * sysdeps/generic/utmp_file.c (setutent_file): Use O_LARGEFILE for
+       open_not_cancel_2.
+       (updwtmp_file): Likewise.
+
+--- libc/sysdeps/generic/utmp_file.c   14 Dec 2005 11:33:40 -0000      1.17
++++ libc/sysdeps/generic/utmp_file.c   15 Mar 2007 20:06:17 -0000      1.18
+@@ -140,11 +140,11 @@ setutent_file (void)
+       file_name = TRANSFORM_UTMP_FILE_NAME (__libc_utmp_file_name);
+-      file_fd = open_not_cancel_2 (file_name, O_RDWR);
++      file_fd = open_not_cancel_2 (file_name, O_RDWR | O_LARGEFILE);
+       if (file_fd == -1)
+       {
+         /* Hhm, read-write access did not work.  Try read-only.  */
+-        file_fd = open_not_cancel_2 (file_name, O_RDONLY);
++        file_fd = open_not_cancel_2 (file_name, O_RDONLY | O_LARGEFILE);
+         if (file_fd == -1)
+           return 0;
+       }
+@@ -459,7 +459,7 @@ updwtmp_file (const char *file, const st
+   int fd;
+   /* Open WTMP file.  */
+-  fd = open_not_cancel_2 (file, O_WRONLY);
++  fd = open_not_cancel_2 (file, O_WRONLY | O_LARGEFILE);
+   if (fd < 0)
+     return -1;
diff --git a/src/patches/glibc/glibc-bz4344.patch b/src/patches/glibc/glibc-bz4344.patch
new file mode 100644 (file)
index 0000000..615d017
--- /dev/null
@@ -0,0 +1,34 @@
+2007-04-13  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #4344]
+       * elf/ldconfig.c (search_dir): Fix 2 off-by-2 errors.
+       Reported by David Anderson <davea42@earthlink.net>.
+
+--- libc/elf/ldconfig.c        3 Jan 2007 05:44:11 -0000       1.58
++++ libc/elf/ldconfig.c        13 Apr 2007 19:53:20 -0000      1.59
+@@ -707,10 +707,10 @@ search_dir (const struct dir_entry *entr
+                        + 1, ".#prelink#.", sizeof (".#prelink#.") - 1) == 0)
+           continue;
+       }
+-      len += strlen (entry->path);
++      len += strlen (entry->path) + 2;
+       if (len > file_name_len)
+       {
+-        file_name_len = len + 1;
++        file_name_len = len;
+         file_name = alloca (file_name_len);
+         if (!opt_chroot)
+           real_file_name = file_name;
+@@ -718,10 +718,10 @@ search_dir (const struct dir_entry *entr
+       sprintf (file_name, "%s/%s", entry->path, direntry->d_name);
+       if (opt_chroot)
+       {
+-        len = strlen (dir_name) + strlen (direntry->d_name);
++        len = strlen (dir_name) + strlen (direntry->d_name) + 2;
+         if (len > real_file_name_len)
+           {
+-            real_file_name_len = len + 1;
++            real_file_name_len = len;
+             real_file_name = alloca (real_file_name_len);
+           }
+         sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name);
diff --git a/src/patches/glibc/glibc-bz4349.patch b/src/patches/glibc/glibc-bz4349.patch
new file mode 100644 (file)
index 0000000..95f55f7
--- /dev/null
@@ -0,0 +1,278 @@
+2007-05-21  Jakub Jelinek  <jakub@redhat.com>
+
+       * malloc/hooks.c (public_sET_STATe): Put all chunks into
+       unsorted chunks and clear {fd,bk}_nextsize fields of largebin
+       chunks.
+
+2007-04-30  Ulrich Drepper  <drepper@redhat.com>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #4349]
+       * malloc/malloc.c: Keep separate list for first blocks on the bin
+       lists with a given size.  This helps skipping over list elements
+       we know won't fit in two places.
+       Inspired by a patch by Tomash Brechko <tomash.brechko@gmail.com>.
+
+--- libc/malloc/malloc.c       2008-05-09 03:52:41.000000000 -0400
++++ libc/malloc/malloc.c       2008-06-24 14:48:40.000000000 -0400
+@@ -1781,6 +1781,10 @@
+   struct malloc_chunk* fd;         /* double links -- used only if free. */
+   struct malloc_chunk* bk;
++
++  /* Only used for large blocks: pointer to next larger size.  */
++  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
++  struct malloc_chunk* bk_nextsize;
+ };
+@@ -1881,7 +1885,7 @@
+ #define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
+ /* The smallest possible chunk */
+-#define MIN_CHUNK_SIZE        (sizeof(struct malloc_chunk))
++#define MIN_CHUNK_SIZE        (offsetof(struct malloc_chunk, fd_nextsize))
+ /* The smallest size we can malloc is an aligned minimal chunk */
+@@ -2081,6 +2085,24 @@
+   else {                                                               \
+     FD->bk = BK;                                                       \
+     BK->fd = FD;                                                       \
++    if (!in_smallbin_range (P->size)                                 \
++      && __builtin_expect (P->fd_nextsize != NULL, 0)) {             \
++      assert (P->fd_nextsize->bk_nextsize == P);                     \
++      assert (P->bk_nextsize->fd_nextsize == P);                     \
++      if (FD->fd_nextsize == NULL) {                                 \
++      if (P->fd_nextsize == P)                                       \
++        FD->fd_nextsize = FD->bk_nextsize = FD;                      \
++      else {                                                         \
++        FD->fd_nextsize = P->fd_nextsize;                            \
++        FD->bk_nextsize = P->bk_nextsize;                            \
++        P->fd_nextsize->bk_nextsize = FD;                            \
++        P->bk_nextsize->fd_nextsize = FD;                            \
++      }                                                              \
++      }       else {                                                         \
++      P->fd_nextsize->bk_nextsize = P->bk_nextsize;                  \
++      P->bk_nextsize->fd_nextsize = P->fd_nextsize;                  \
++      }                                                                      \
++    }                                                                \
+   }                                                                    \
+ }
+@@ -2786,7 +2808,31 @@
+         /* lists are sorted */
+         assert(p->bk == b ||
+                (unsigned long)chunksize(p->bk) >= (unsigned long)chunksize(p));
+-      }
++
++      if (!in_smallbin_range(size))
++        {
++          if (p->fd_nextsize != NULL)
++            {
++              if (p->fd_nextsize == p)
++                assert (p->bk_nextsize == p);
++              else
++                {
++                  if (p->fd_nextsize == first (b))
++                    assert (chunksize (p) < chunksize (p->fd_nextsize));
++                  else
++                    assert (chunksize (p) > chunksize (p->fd_nextsize));
++
++                  if (p == first (b))
++                    assert (chunksize (p) > chunksize (p->bk_nextsize));
++                  else
++                    assert (chunksize (p) < chunksize (p->bk_nextsize));
++                }
++            }
++          else
++            assert (p->bk_nextsize == NULL);
++        }
++      } else if (!in_smallbin_range(size))
++      assert (p->fd_nextsize == NULL && p->bk_nextsize == NULL);
+       /* chunk is followed by a legal chain of inuse chunks */
+       for (q = next_chunk(p);
+            (q != av->top && inuse(q) &&
+@@ -4135,6 +4181,11 @@
+         unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
+         av->last_remainder = remainder;
+         remainder->bk = remainder->fd = unsorted_chunks(av);
++      if (!in_smallbin_range(remainder_size))
++        {
++          remainder->fd_nextsize = NULL;
++          remainder->bk_nextsize = NULL;
++        }
+         set_head(victim, nb | PREV_INUSE |
+                (av != &main_arena ? NON_MAIN_ARENA : 0));
+@@ -4183,19 +4234,36 @@
+           size |= PREV_INUSE;
+           /* if smaller than smallest, bypass loop below */
+         assert((bck->bk->size & NON_MAIN_ARENA) == 0);
+-          if ((unsigned long)(size) <= (unsigned long)(bck->bk->size)) {
++        if ((unsigned long)(size) < (unsigned long)(bck->bk->size)) {
+             fwd = bck;
+             bck = bck->bk;
++
++          victim->fd_nextsize = fwd->fd;
++          victim->bk_nextsize = fwd->fd->bk_nextsize;
++          fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim;
+           }
+           else {
+           assert((fwd->size & NON_MAIN_ARENA) == 0);
+-            while ((unsigned long)(size) < (unsigned long)(fwd->size)) {
+-              fwd = fwd->fd;
+-            assert((fwd->size & NON_MAIN_ARENA) == 0);
+-          }
+-            bck = fwd->bk;
++          while ((unsigned long) size < fwd->size)
++            {
++              fwd = fwd->fd_nextsize;
++              assert((fwd->size & NON_MAIN_ARENA) == 0);
++            }
++
++          if ((unsigned long) size == (unsigned long) fwd->size)
++            /* Always insert in the second position.  */
++            fwd = fwd->fd;
++          else
++            {
++              victim->fd_nextsize = fwd;
++              victim->bk_nextsize = fwd->bk_nextsize;
++              fwd->bk_nextsize = victim;
++              victim->bk_nextsize->fd_nextsize = victim;
++            }
++          bck = fwd->bk;
+           }
+-        }
++      } else
++        victim->fd_nextsize = victim->bk_nextsize = victim;
+       }
+       mark_bin(av, victim_index);
+@@ -4213,21 +4281,25 @@
+     /*
+       If a large request, scan through the chunks of current bin in
+-      sorted order to find smallest that fits.  This is the only step
+-      where an unbounded number of chunks might be scanned without doing
+-      anything useful with them. However the lists tend to be short.
++      sorted order to find smallest that fits.  Use the skip list for this.
+     */
+     if (!in_smallbin_range(nb)) {
+       bin = bin_at(av, idx);
+       /* skip scan if empty or largest chunk is too small */
+-      if ((victim = last(bin)) != bin &&
+-          (unsigned long)(first(bin)->size) >= (unsigned long)(nb)) {
++      if ((victim = first(bin)) != bin &&
++          (unsigned long)(victim->size) >= (unsigned long)(nb)) {
++      victim = victim->bk_nextsize;
+         while (((unsigned long)(size = chunksize(victim)) <
+                 (unsigned long)(nb)))
+-          victim = victim->bk;
++          victim = victim->bk_nextsize;
++
++      /* Avoid removing the first entry for a size so that the skip
++         list does not have to be rerouted.  */
++      if (victim != last(bin) && victim->size == victim->fd->size)
++        victim = victim->fd;
+         remainder_size = size - nb;
+         unlink(victim, bck, fwd);
+@@ -4249,6 +4321,11 @@
+         remainder->fd = fwd;
+         bck->fd = remainder;
+         fwd->bk = remainder;
++        if (!in_smallbin_range(remainder_size))
++          {
++            remainder->fd_nextsize = NULL;
++            remainder->bk_nextsize = NULL;
++          }
+           set_head(victim, nb | PREV_INUSE |
+                  (av != &main_arena ? NON_MAIN_ARENA : 0));
+           set_head(remainder, remainder_size | PREV_INUSE);
+@@ -4318,9 +4395,7 @@
+         remainder_size = size - nb;
+         /* unlink */
+-        bck = victim->bk;
+-        bin->bk = bck;
+-        bck->fd = bin;
++        unlink(victim, bck, fwd);
+         /* Exhaust */
+         if (remainder_size < MINSIZE) {
+@@ -4345,7 +4420,11 @@
+           /* advertise as last remainder */
+           if (in_smallbin_range(nb))
+             av->last_remainder = remainder;
+-
++        if (!in_smallbin_range(remainder_size))
++          {
++            remainder->fd_nextsize = NULL;
++            remainder->bk_nextsize = NULL;
++          }
+           set_head(victim, nb | PREV_INUSE |
+                  (av != &main_arena ? NON_MAIN_ARENA : 0));
+           set_head(remainder, remainder_size | PREV_INUSE);
+@@ -4568,8 +4647,13 @@
+       bck = unsorted_chunks(av);
+       fwd = bck->fd;
+-      p->bk = bck;
+       p->fd = fwd;
++      p->bk = bck;
++      if (!in_smallbin_range(size))
++      {
++        p->fd_nextsize = NULL;
++        p->bk_nextsize = NULL;
++      }
+       bck->fd = p;
+       fwd->bk = p;
+@@ -4729,6 +4813,11 @@
+             unsorted_bin->fd = p;
+             first_unsorted->bk = p;
++            if (!in_smallbin_range (size)) {
++            p->fd_nextsize = NULL;
++            p->bk_nextsize = NULL;
++          }
++
+             set_head(p, size | PREV_INUSE);
+             p->bk = unsorted_bin;
+             p->fd = first_unsorted;
+--- libc/malloc/hooks.c.jj     2005-11-21 10:43:04.000000000 -0500
++++ libc/malloc/hooks.c        2008-05-09 03:54:00.000000000 -0400
+@@ -595,8 +595,9 @@ public_sET_STATe(Void_t* msptr)
+       assert(ms->av[2*i+3] == 0);
+       first(b) = last(b) = b;
+     } else {
+-      if(i<NSMALLBINS || (largebin_index(chunksize(ms->av[2*i+2]))==i &&
+-                        largebin_index(chunksize(ms->av[2*i+3]))==i)) {
++      if(0 &&
++       (i<NSMALLBINS || (largebin_index(chunksize(ms->av[2*i+2]))==i &&
++                         largebin_index(chunksize(ms->av[2*i+3]))==i))) {
+       first(b) = ms->av[2*i+2];
+       last(b) = ms->av[2*i+3];
+       /* Make sure the links to the bins within the heap are correct.  */
+@@ -616,6 +617,17 @@ public_sET_STATe(Void_t* msptr)
+       }
+     }
+   }
++  if (1) {
++    /* Clear fd_nextsize and bk_nextsize fields.  */
++    b = unsorted_chunks(&main_arena)->fd;
++    while (b != unsorted_chunks(&main_arena)) {
++      if (!in_smallbin_range(chunksize(b))) {
++      b->fd_nextsize = NULL;
++      b->bk_nextsize = NULL;
++      }
++      b = b->fd;
++    }
++  }
+   mp_.sbrk_base = ms->sbrk_base;
+   main_arena.system_mem = ms->sbrked_mem_bytes;
+   mp_.trim_threshold = ms->trim_threshold;
diff --git a/src/patches/glibc/glibc-bz4364.patch b/src/patches/glibc/glibc-bz4364.patch
new file mode 100644 (file)
index 0000000..836a09b
--- /dev/null
@@ -0,0 +1,18 @@
+2007-04-16  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #4364]
+       * posix/unistd.h (_XOPEN_VERSION): Define appropriately for SUSv3.
+
+--- libc/posix/unistd.h        9 Nov 2006 21:51:58 -0000       1.148
++++ libc/posix/unistd.h        16 Apr 2007 23:44:06 -0000      1.149
+@@ -56,7 +56,9 @@ __BEGIN_DECLS
+ #define _POSIX2_LOCALEDEF       200112L
+ /* X/Open version number to which the library conforms.  It is selectable.  */
+-#ifdef __USE_UNIX98
++#ifdef __USE_XOPEN2K
++# define _XOPEN_VERSION       600
++#elif defined __USE_UNIX98
+ # define _XOPEN_VERSION       500
+ #else
+ # define _XOPEN_VERSION       4
diff --git a/src/patches/glibc/glibc-bz4405.patch b/src/patches/glibc/glibc-bz4405.patch
new file mode 100644 (file)
index 0000000..58c0652
--- /dev/null
@@ -0,0 +1,17 @@
+2007-04-23  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #4405]
+       * iconvdata/gconv-modules (E13B): Add a missing slash to the alias
+       name.  Patch by Aurelien Jarno <aurelien@aurel32.net>.
+
+--- libc/iconvdata/gconv-modules       20 Jan 2007 00:22:40 -0000      1.90
++++ libc/iconvdata/gconv-modules       23 Apr 2007 09:22:10 -0000      1.91
+@@ -1376,7 +1376,7 @@ module   INTERNAL                INIS-CYRILLIC//         INIS-C
+ #     from                    to                      module          cost
+ alias ISO-IR-98//             ISO_2033//
+ alias ISO_2033-1983//         ISO_2033//
+-alias E13B/                   ISO_2033//
++alias E13B//                  ISO_2033//
+ alias CSISO2033//             ISO_2033//
+ module        ISO_2033//              INTERNAL                ISO_2033        1
+ module        INTERNAL                ISO_2033//              ISO_2033        1
diff --git a/src/patches/glibc/glibc-bz4438.patch b/src/patches/glibc/glibc-bz4438.patch
new file mode 100644 (file)
index 0000000..d61f8e0
--- /dev/null
@@ -0,0 +1,81 @@
+2007-05-04  Ulrich Drepper  <drepper@redhat.com>
+
+       * stdio-common/vfprintf.c (process_string_arg): Adjust call to
+       __mbsnrtowcs after last change.
+
+2007-05-02  Jakub Jelinek  <jakub@redhat.com>
+
+       * stdio-common/vfprintf.c (process_string_arg): Use a VLA rather than
+       fixed length array for ignore.
+
+2007-04-30  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #4438]
+       * stdio-common/vfprintf.c (process_string_arg): Don't overflow the
+       stack for large precisions.
+       * stdio-common/test-vfprintf.c (main): Add test for large
+       precision.
+
+--- libc/stdio-common/vfprintf.c       17 Mar 2007 17:08:56 -0000      1.135
++++ libc/stdio-common/vfprintf.c       5 May 2007 04:41:35 -0000       1.138
+@@ -1160,19 +1160,26 @@ vfprintf (FILE *s, const CHAR_T *format,
+               else                                                          \
+                 {                                                           \
+                   /* In case we have a multibyte character set the          \
+-                     situation is more compilcated.  We must not copy       \
++                     situation is more complicated.  We must not copy       \
+                      bytes at the end which form an incomplete character. */\
+-                  wchar_t ignore[prec];                                     \
++                  size_t ignore_size = (unsigned) prec > 1024 ? 1024 : prec;\
++                  wchar_t ignore[ignore_size];                              \
+                   const char *str2 = string;                                \
+-                  mbstate_t ps;                                             \
++                  const char *strend = string + prec;                       \
++                  if (strend < string)                                      \
++                    strend = (const char *) UINTPTR_MAX;                    \
+                                                                             \
++                  mbstate_t ps;                                             \
+                   memset (&ps, '\0', sizeof (ps));                          \
+-                  if (__mbsnrtowcs (ignore, &str2, prec, prec, &ps)         \
+-                      == (size_t) -1)                                       \
+-                    {                                                       \
+-                      done = -1;                                            \
+-                      goto all_done;                                        \
+-                    }                                                       \
++                                                                            \
++                  while (str2 != NULL && str2 < strend)                     \
++                    if (__mbsnrtowcs (ignore, &str2, strend - str2,         \
++                                      ignore_size, &ps) == (size_t) -1)     \
++                      {                                                     \
++                        done = -1;                                          \
++                        goto all_done;                                      \
++                      }                                                     \
++                                                                            \
+                   if (str2 == NULL)                                         \
+                     len = strlen (string);                                  \
+                   else                                                      \
+--- libc/stdio-common/test-vfprintf.c  19 Aug 2003 20:23:55 -0000      1.4
++++ libc/stdio-common/test-vfprintf.c  1 May 2007 18:35:32 -0000       1.5
+@@ -94,6 +94,7 @@ main (void)
+       fprintf (fp, "%.*s", 30000, large);
+       large[20000] = '\0';
+       fprintf (fp, large);
++      fprintf (fp, "%-1.300000000s", "hello");
+       if (fflush (fp) != 0 || ferror (fp) != 0 || fclose (fp) != 0)
+       {
+@@ -108,11 +109,12 @@ main (void)
+                 setlocale (LC_ALL, NULL));
+         exit (1);
+       }
+-      else if (st.st_size != 99999)
++      else if (st.st_size != 50000 + 30000 + 19999 + 5)
+       {
+         printf ("file size incorrect for locale %s: %jd instead of %jd\n",
+                 setlocale (LC_ALL, NULL),
+-                (intmax_t) st.st_size, (intmax_t) 99999);
++                (intmax_t) st.st_size,
++                (intmax_t) 50000 + 30000 + 19999 + 5);
+         res = 1;
+       }
+       else
diff --git a/src/patches/glibc/glibc-bz4439.patch b/src/patches/glibc/glibc-bz4439.patch
new file mode 100644 (file)
index 0000000..7074e92
--- /dev/null
@@ -0,0 +1,144 @@
+2007-04-30  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #4439]
+       * resolv/inet_ntop.c (inet_ntop4): Take terminating '\0' into
+       account in the size check.
+       * resolv/tst-inet_ntop.c: New test.
+       * resolv/Makefile (tests): Add tst-inet_ntop.
+
+--- libc/resolv/Makefile       15 Aug 2004 20:21:59 -0000      1.48
++++ libc/resolv/Makefile       30 Apr 2007 22:30:05 -0000      1.49
+@@ -32,7 +32,7 @@ distribute := ../conf/portability.h mapv
+ routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \
+           res_hconf res_libc res-state
+-tests = tst-aton tst-leaks
++tests = tst-aton tst-leaks tst-inet_ntop
+ xtests = tst-leaks2
+ generate := mtrace-tst-leaks tst-leaks.mtrace tst-leaks2.mtrace
+--- libc/resolv/inet_ntop.c    3 Aug 2002 12:08:47 -0000       1.9
++++ libc/resolv/inet_ntop.c    30 Apr 2007 22:29:33 -0000      1.10
+@@ -96,7 +96,7 @@ inet_ntop4(src, dst, size)
+       static const char fmt[] = "%u.%u.%u.%u";
+       char tmp[sizeof "255.255.255.255"];
+-      if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) {
++      if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) >= size) {
+               __set_errno (ENOSPC);
+               return (NULL);
+       }
+--- libc/resolv/tst-inet_ntop.c        1 Jan 1970 00:00:00 -0000
++++ libc/resolv/tst-inet_ntop.c        30 Apr 2007 22:29:21 -0000      1.1
+@@ -0,0 +1,111 @@
++#include <arpa/inet.h>
++#include <errno.h>
++#include <netinet/in.h>
++#include <stdio.h>
++#include <string.h>
++
++int
++main (void)
++{
++  struct in_addr addr4;
++  struct in6_addr addr6;
++  char buf[64];
++  int result = 0;
++
++  addr4.s_addr = 0xe0e0e0e0;
++  addr6.s6_addr16[0] = 0;
++  addr6.s6_addr16[1] = 0;
++  addr6.s6_addr16[2] = 0;
++  addr6.s6_addr16[3] = 0;
++  addr6.s6_addr16[4] = 0;
++  addr6.s6_addr16[5] = 0xffff;
++  addr6.s6_addr32[3] = 0xe0e0e0e0;
++  memset (buf, 'x', sizeof buf);
++
++  if (inet_ntop (AF_INET, &addr4, buf, 15) != NULL)
++    {
++      puts ("1st inet_ntop returned non-NULL");
++      result++;
++    }
++  else if (errno != ENOSPC)
++    {
++      puts ("1st inet_ntop didn't fail with ENOSPC");
++      result++;
++    }
++  if (buf[15] != 'x')
++    {
++      puts ("1st inet_ntop wrote past the end of buffer");
++      result++;
++    }
++
++  if (inet_ntop (AF_INET, &addr4, buf, 16) != buf)
++    {
++      puts ("2nd inet_ntop did not return buf");
++      result++;
++    }
++  if (memcmp (buf, "224.224.224.224\0" "xxxxxxxx", 24) != 0)
++    {
++      puts ("2nd inet_ntop wrote past the end of buffer");
++      result++;
++    }
++
++  if (inet_ntop (AF_INET6, &addr6, buf, 22) != NULL)
++    {
++      puts ("3rd inet_ntop returned non-NULL");
++      result++;
++    }
++  else if (errno != ENOSPC)
++    {
++      puts ("3rd inet_ntop didn't fail with ENOSPC");
++      result++;
++    }
++  if (buf[22] != 'x')
++    {
++      puts ("3rd inet_ntop wrote past the end of buffer");
++      result++;
++    }
++
++  if (inet_ntop (AF_INET6, &addr6, buf, 23) != buf)
++    {
++      puts ("4th inet_ntop did not return buf");
++      result++;
++    }
++  if (memcmp (buf, "::ffff:224.224.224.224\0" "xxxxxxxx", 31) != 0)
++    {
++      puts ("4th inet_ntop wrote past the end of buffer");
++      result++;
++    }
++
++  memset (&addr6.s6_addr, 0xe0, sizeof (addr6.s6_addr));
++
++  if (inet_ntop (AF_INET6, &addr6, buf, 39) != NULL)
++    {
++      puts ("5th inet_ntop returned non-NULL");
++      result++;
++    }
++  else if (errno != ENOSPC)
++    {
++      puts ("5th inet_ntop didn't fail with ENOSPC");
++      result++;
++    }
++  if (buf[39] != 'x')
++    {
++      puts ("5th inet_ntop wrote past the end of buffer");
++      result++;
++    }
++
++  if (inet_ntop (AF_INET6, &addr6, buf, 40) != buf)
++    {
++      puts ("6th inet_ntop did not return buf");
++      result++;
++    }
++  if (memcmp (buf, "e0e0:e0e0:e0e0:e0e0:e0e0:e0e0:e0e0:e0e0\0"
++                 "xxxxxxxx", 48) != 0)
++    {
++      puts ("6th inet_ntop wrote past the end of buffer");
++      result++;
++    }
++
++  
++  return result;
++}
diff --git a/src/patches/glibc/glibc-bz4514.patch b/src/patches/glibc/glibc-bz4514.patch
new file mode 100644 (file)
index 0000000..fa37c91
--- /dev/null
@@ -0,0 +1,79 @@
+2007-05-21  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #4514]
+       * stdio-common/vfprintf.c (vfprintf): Don't shadow workstart variable,
+       reinitialize workend at the start of each do_positional format spec
+       loop, free workstart before do_positional loops.
+       (printf_unknown): Fix size of work_buffer.
+       * stdio-common/tst-sprintf.c (main): Add 3 new testcases.
+
+--- libc/stdio-common/vfprintf.c       7 May 2007 03:43:55 -0000       1.139
++++ libc/stdio-common/vfprintf.c       21 May 2007 17:50:22 -0000      1.140
+@@ -1627,6 +1627,8 @@ do_positional:
+     /* Just a counter.  */
+     size_t cnt;
++    free (workstart);
++    workstart = NULL;
+     if (grouping == (const char *) -1)
+       {
+@@ -1801,7 +1803,9 @@ do_positional:
+       int use_outdigits = specs[nspecs_done].info.i18n;
+       char pad = specs[nspecs_done].info.pad;
+       CHAR_T spec = specs[nspecs_done].info.spec;
+-      CHAR_T *workstart = NULL;
++
++      workstart = NULL;
++      workend = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)];
+       /* Fill in last information.  */
+       if (specs[nspecs_done].width_arg != -1)
+@@ -1897,8 +1901,7 @@ do_positional:
+           break;
+         }
+-      if (__builtin_expect (workstart != NULL, 0))
+-        free (workstart);
++      free (workstart);
+       workstart = NULL;
+       /* Write the following constant string.  */
+@@ -1926,7 +1929,7 @@ printf_unknown (FILE *s, const struct pr
+ {
+   int done = 0;
+-  CHAR_T work_buffer[MAX (info->width, info->spec) + 32];
++  CHAR_T work_buffer[MAX (sizeof (info->width), sizeof (info->prec)) * 3];
+   CHAR_T *const workend
+     = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)];
+   register CHAR_T *w;
+--- libc/stdio-common/tst-sprintf.c    25 Jun 2003 11:04:49 -0000      1.3
++++ libc/stdio-common/tst-sprintf.c    21 May 2007 17:50:42 -0000      1.4
+@@ -37,5 +37,26 @@ main (void)
+       free (dst);
+     }
++  if (sprintf (buf, "%1$d%3$.*2$s%4$d", 7, 67108863, "x", 8) != 3
++      || strcmp (buf, "7x8") != 0)
++    {
++      printf ("sprintf (buf, \"%%1$d%%3$.*2$s%%4$d\", 7, 67108863, \"x\", 8) produced `%s' output", buf);
++      result = 1;
++    }
++
++  if (sprintf (buf, "%67108863.16\"%d", 7) != 14
++      || strcmp (buf, "%67108863.16\"7") != 0)
++    {
++      printf ("sprintf (buf, \"%%67108863.16\\\"%%d\", 7) produced `%s' output", buf);
++      result = 1;
++    }
++
++  if (sprintf (buf, "%*\"%d", 0x3ffffff, 7) != 11
++      || strcmp (buf, "%67108863\"7") != 0)
++    {
++      printf ("sprintf (buf, \"%%*\\\"%%d\", 0x3ffffff, 7) produced `%s' output", buf);
++      result = 1;
++    }
++
+   return result;
+ }
diff --git a/src/patches/glibc/glibc-bz4586.patch b/src/patches/glibc/glibc-bz4586.patch
new file mode 100644 (file)
index 0000000..4ec883c
--- /dev/null
@@ -0,0 +1,50 @@
+2007-06-06  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #4586]
+       * sysdeps/i386/ldbl2mpn.c (__mpn_extract_long_double): Treat
+       pseudo-zeros as zero.
+       * sysdeps/x86_64/ldbl2mpn.c: New file.
+       * sysdeps/ia64/ldbl2mpn.c: New file.
+
+--- libc/sysdeps/i386/ldbl2mpn.c       6 Jul 2001 04:55:52 -0000       1.4
++++ libc/sysdeps/i386/ldbl2mpn.c       8 Jun 2007 02:50:11 -0000       1.5
+@@ -19,7 +19,7 @@
+ #include "gmp.h"
+ #include "gmp-impl.h"
+ #include "longlong.h"
+-#include "ieee754.h"
++#include <ieee754.h>
+ #include <float.h>
+ #include <stdlib.h>
+@@ -46,7 +46,7 @@ __mpn_extract_long_double (mp_ptr res_pt
+ #elif BITS_PER_MP_LIMB == 64
+   /* Hopefully the compiler will combine the two bitfield extracts
+      and this composition into just the original quadword extract.  */
+-  res_ptr[0] = ((unsigned long int) u.ieee.mantissa0 << 32) | u.ieee.mantissa1;
++  res_ptr[0] = ((mp_limb_t) u.ieee.mantissa0 << 32) | u.ieee.mantissa1;
+   #define N 1
+ #else
+   #error "mp_limb size " BITS_PER_MP_LIMB "not accounted for"
+@@ -109,6 +109,13 @@ __mpn_extract_long_double (mp_ptr res_pt
+           }
+       }
+     }
++  else if (u.ieee.exponent < 0x7fff
++#if N == 2
++         && res_ptr[0] == 0
++#endif
++         && res_ptr[N - 1] == 0)
++    /* Pseudo zero.  */
++    *expt = 0;
+   return N;
+ }
+--- libc/sysdeps/ia64/ldbl2mpn.c       1 Jan 1970 00:00:00 -0000
++++ libc/sysdeps/ia64/ldbl2mpn.c       8 Jun 2007 02:50:49 -0000       1.1
+@@ -0,0 +1 @@
++#include "../i386/ldbl2mpn.c"
+--- libc/sysdeps/x86_64/ldbl2mpn.c     1 Jan 1970 00:00:00 -0000
++++ libc/sysdeps/x86_64/ldbl2mpn.c     8 Jun 2007 02:50:35 -0000       1.1
+@@ -0,0 +1 @@
++#include "../i386/ldbl2mpn.c"
diff --git a/src/patches/glibc/glibc-bz4702.patch b/src/patches/glibc/glibc-bz4702.patch
new file mode 100644 (file)
index 0000000..1c10cdf
--- /dev/null
@@ -0,0 +1,32 @@
+2007-07-03  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #4702]
+       * nis/nss-default.c: Include errno.h.
+       (init): Preserve errno.
+
+--- libc/nis/nss-default.c     28 Apr 2006 21:03:17 -0000      1.3
++++ libc/nis/nss-default.c     3 Jul 2007 14:49:41 -0000       1.4
+@@ -17,6 +17,7 @@
+    02111-1307 USA.  */
+ #include <ctype.h>
++#include <errno.h>
+ #include <stdio.h>
+ #include <stdio_ext.h>
+ #include <stdlib.h>
+@@ -54,6 +55,7 @@ static const struct
+ static void
+ init (void)
+ {
++  int saved_errno = errno;
+   FILE *fp = fopen (default_nss, "rc");
+   if (fp != NULL)
+     {
+@@ -111,6 +113,7 @@ init (void)
+       fclose (fp);
+     }
++  __set_errno (saved_errno);
+ }
diff --git a/src/patches/glibc/glibc-bz4745.patch b/src/patches/glibc/glibc-bz4745.patch
new file mode 100644 (file)
index 0000000..9f674b4
--- /dev/null
@@ -0,0 +1,169 @@
+2007-07-07  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #4745]
+       * stdio-common/vfscanf.c (_IO_vfscanf): Add additional test for EOF
+       in loop to look for conversion specifier to avoid testing of
+       wrong errno value.
+       * stdio-common/Makefile (tests): Add bug18, bug18a, bug19, bug19a.
+       * stdio-common/bug18.c: New file.
+       * stdio-common/bug18a.c: New file.
+       * stdio-common/bug19.c: New file.
+       * stdio-common/bug19a.c: New file.
+
+--- libc/stdio-common/vfscanf.c        27 Apr 2007 19:28:32 -0000      1.123
++++ libc/stdio-common/vfscanf.c        8 Jul 2007 04:41:22 -0000       1.124
+@@ -549,7 +549,11 @@ _IO_vfscanf (s, format, argptr, errp)
+         int save_errno = errno;
+         errno = 0;
+         do
+-          if (inchar () == EOF && errno == EINTR)
++          /* We add the additional test for EOF here since otherwise
++             inchar will restore the old errno value which might be
++             EINTR but does not indicate an interrupt since nothing
++             was read at this time.  */
++          if ((c == EOF || inchar () == EOF) && errno == EINTR)
+             input_error ();
+         while (ISSPACE (c));
+         errno = save_errno;
+--- libc/stdio-common/Makefile 4 Jun 2007 14:38:03 -0000       1.101
++++ libc/stdio-common/Makefile 8 Jul 2007 04:41:08 -0000       1.104
+@@ -54,7 +54,7 @@ tests := tstscanf test_rdwr test-popen t
+        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 bug17
++       tst-fwrite bug16 bug17 bug18 bug18a bug19 bug19a
+ test-srcs = tst-unbputc tst-printf
+--- libc/stdio-common/bug18.c  1 Jan 1970 00:00:00 -0000
++++ libc/stdio-common/bug18.c  7 Jul 2007 21:37:37 -0000       1.2
+@@ -0,0 +1,48 @@
++#include <assert.h>
++#include <errno.h>
++#include <stdio.h>
++
++#ifndef CHAR
++# define CHAR char
++# define L(str) str
++# define SSCANF sscanf
++#endif
++
++
++static int
++do_test (void)
++{
++  printf("setting errno to EINTR\n");
++  errno = EINTR;
++
++  printf("checking sscanf\n");
++
++  CHAR str[] = L("7-11");
++  int i, j, n;
++
++  i = j = n = 0;
++  SSCANF (str, L(" %i - %i %n"), &i, &j, &n);
++  printf ("found %i-%i (length=%i)\n", i, j, n);
++
++  int result = 0;
++  if (i != 7)
++    {
++      printf ("i is %d, expected 7\n", i);
++      result = 1;
++    }
++  if (j != 11)
++    {
++      printf ("j is %d, expected 11\n", j);
++      result = 1;
++    }
++  if (n != 4)
++    {
++      printf ("n is %d, expected 4\n", j);
++      result = 1;
++    }
++
++  return result;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/stdio-common/bug18a.c 1 Jan 1970 00:00:00 -0000
++++ libc/stdio-common/bug18a.c 7 Jul 2007 21:38:10 -0000       1.1
+@@ -0,0 +1,6 @@
++#include <wchar.h>
++#define CHAR wchar_t
++#define L(str) L##str
++#define SSCANF swscanf
++
++#include "bug18.c"
+--- libc/stdio-common/bug19.c  1 Jan 1970 00:00:00 -0000
++++ libc/stdio-common/bug19.c  8 Jul 2007 04:40:55 -0000       1.1
+@@ -0,0 +1,58 @@
++#include <assert.h>
++#include <errno.h>
++#include <stdio.h>
++
++#ifndef CHAR
++# define CHAR char
++# define L(str) str
++# define FPUTS fputs
++# define FSCANF fscanf
++#endif
++
++
++static int
++do_test (void)
++{
++  FILE *fp = tmpfile ();
++  if (fp == NULL)
++    {
++      puts ("cannot open file");
++      return 1;
++    }
++
++  FPUTS (L("7-11"), fp);
++  rewind (fp);
++
++  printf("setting errno to EINTR\n");
++  errno = EINTR;
++
++  printf("checking sscanf\n");
++
++  int i, j, n;
++
++  i = j = n = 0;
++  FSCANF (fp, L(" %i - %i %n"), &i, &j, &n);
++  printf ("found %i-%i (length=%i)\n", i, j, n);
++
++  int result = 0;
++  if (i != 7)
++    {
++      printf ("i is %d, expected 7\n", i);
++      result = 1;
++    }
++  if (j != 11)
++    {
++      printf ("j is %d, expected 11\n", j);
++      result = 1;
++    }
++  if (n != 4)
++    {
++      printf ("n is %d, expected 4\n", j);
++      result = 1;
++    }
++
++  return result;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/stdio-common/bug19a.c 1 Jan 1970 00:00:00 -0000
++++ libc/stdio-common/bug19a.c 8 Jul 2007 04:40:55 -0000       1.1
+@@ -0,0 +1,7 @@
++#include <wchar.h>
++#define CHAR wchar_t
++#define L(str) L##str
++#define FPUTS fputws
++#define FSCANF fwscanf
++
++#include "bug19.c"
diff --git a/src/patches/glibc/glibc-bz4776.patch b/src/patches/glibc/glibc-bz4776.patch
new file mode 100644 (file)
index 0000000..10472e6
--- /dev/null
@@ -0,0 +1,86 @@
+2007-07-11  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #4776]
+       * elf/dl-load.c (_dl_rtld_di_serinfo): Output / in LD_LIBRARY_PATH,
+       RPATH etc. as "/" rather than "", don't segfault on empty paths,
+       instead output ".".
+       * dlfcn/Makefile (distribute): Add glreflib3.c.
+       (module-names): Add glreflib3.
+       ($(objpfx)tst-dlinfo.out): Depend on glreflib3.so rather than
+       glreflib1.so.
+       (LDFLAGS_glreflib3.so): New.
+       * dlfcn/tst-dlinfo.c (do_test): Load glreflib3.so instead of
+       glreflib1.so.
+       * dlfcn/glreflib3.c: New file.
+
+--- libc/elf/dl-load.c 30 Jun 2007 17:01:07 -0000      1.286
++++ libc/elf/dl-load.c 12 Jul 2007 18:15:27 -0000      1.287
+@@ -2273,14 +2273,17 @@ _dl_rtld_di_serinfo (struct link_map *lo
+             if (counting)
+               {
+                 si->dls_cnt++;
+-                si->dls_size += r->dirnamelen;
++                si->dls_size += r->dirnamelen < 2 ? r->dirnamelen : 2;
+               }
+             else
+               {
+                 Dl_serpath *const sp = &si->dls_serpath[idx++];
+                 sp->dls_name = allocptr;
+-                allocptr = __mempcpy (allocptr,
+-                                      r->dirname, r->dirnamelen - 1);
++                if (r->dirnamelen < 2)
++                  *allocptr++ = r->dirnamelen ? '/' : '.';
++                else
++                  allocptr = __mempcpy (allocptr,
++                                        r->dirname, r->dirnamelen - 1);
+                 *allocptr++ = '\0';
+                 sp->dls_flags = flags;
+               }
+--- libc/dlfcn/Makefile        28 Oct 2006 06:44:04 -0000      1.42
++++ libc/dlfcn/Makefile        12 Jul 2007 18:16:10 -0000      1.43
+@@ -23,7 +23,8 @@ libdl-routines       := dlopen dlclose dlsym d
+                  dlmopen
+ routines      := $(patsubst %,s%,$(libdl-routines))
+ elide-routines.os := $(routines)
+-distribute    := dlopenold.c glreflib1.c glreflib2.c failtestmod.c \
++distribute    := dlopenold.c glreflib1.c glreflib2.c glreflib3.c \
++                 failtestmod.c \
+                  defaultmod1.c defaultmod2.c errmsg1mod.c modatexit.c \
+                  modcxaatexit.c modstatic.c modstatic2.c \
+                  bug-dlsym1-lib1.c bug-dlsym1-lib2.c
+@@ -44,8 +45,8 @@ ifeq (yes,$(have-protected))
+ tests += tstatexit
+ endif
+ endif
+-modules-names = glreflib1 glreflib2 failtestmod defaultmod1 defaultmod2 \
+-              errmsg1mod modatexit modcxaatexit \
++modules-names = glreflib1 glreflib2 glreflib3 failtestmod defaultmod1 \
++              defaultmod2 errmsg1mod modatexit modcxaatexit \
+               bug-dlsym1-lib1 bug-dlsym1-lib2
+ failtestmod.so-no-z-defs = yes
+@@ -87,7 +88,8 @@ $(objpfx)tst-dladdr: $(libdl)
+ $(objpfx)tst-dladdr.out: $(objpfx)glreflib1.so
+ $(objpfx)tst-dlinfo: $(libdl)
+-$(objpfx)tst-dlinfo.out: $(objpfx)glreflib1.so
++$(objpfx)tst-dlinfo.out: $(objpfx)glreflib3.so
++LDFLAGS-glreflib3.so = -Wl,-rpath,:
+ LDFLAGS-default = $(LDFLAGS-rdynamic)
+ $(objpfx)default: $(libdl) $(objpfx)defaultmod1.so $(objpfx)defaultmod2.so
+--- libc/dlfcn/glreflib3.c     1 Jan 1970 00:00:00 -0000
++++ libc/dlfcn/glreflib3.c     12 Jul 2007 18:15:56 -0000      1.1
+@@ -0,0 +1 @@
++#include "glreflib1.c"
+--- libc/dlfcn/tst-dlinfo.c    15 Mar 2003 23:14:48 -0000      1.1
++++ libc/dlfcn/tst-dlinfo.c    12 Jul 2007 18:15:39 -0000      1.2
+@@ -29,7 +29,7 @@ do_test (void)
+ {
+   int status = 0;
+-  void *handle = dlopen ("glreflib1.so", RTLD_NOW);
++  void *handle = dlopen ("glreflib3.so", RTLD_NOW);
+   if (handle == NULL)
+     error (EXIT_FAILURE, 0, "cannot load: glreflib1.so: %s", dlerror ());
diff --git a/src/patches/glibc/glibc-bz4813.patch b/src/patches/glibc/glibc-bz4813.patch
new file mode 100644 (file)
index 0000000..798ed7f
--- /dev/null
@@ -0,0 +1,18 @@
+2007-07-20  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #4813]
+       * login/forkpty.c (forkpty): Close master and slave fds on
+       fork failure.  Patch by
+       Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>.
+
+--- libc/login/forkpty.c       6 Jul 2001 04:55:34 -0000       1.2
++++ libc/login/forkpty.c       20 Jul 2007 07:20:07 -0000      1.3
+@@ -38,6 +38,8 @@ forkpty (amaster, name, termp, winp)
+   switch (pid = fork ())
+     {
+     case -1:
++      close (master);
++      close (slave);
+       return -1;
+     case 0:
+       /* Child.  */
diff --git a/src/patches/glibc/glibc-bz4858.patch b/src/patches/glibc/glibc-bz4858.patch
new file mode 100644 (file)
index 0000000..2cf2403
--- /dev/null
@@ -0,0 +1,48 @@
+2007-07-31  Jakub Jelinek  <jakub@redhat.com>
+
+       * stdio-common/tfformat.c (sprint_doubles): Add 12 new tests.
+
+2007-07-28  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #4858]
+       * stdio-common/printf_fp.c (___printf_fp): Fix special case of
+       #.0g and value rounded to 1.0.
+       * stdio-common/tfformat.c (sprint_doubles): Add two new tests.
+
+--- libc/stdio-common/printf_fp.c      30 Apr 2007 22:31:21 -0000      1.63
++++ libc/stdio-common/printf_fp.c      29 Jul 2007 00:25:19 -0000      1.64
+@@ -986,7 +986,9 @@ ___printf_fp (FILE *fp,
+           if (*wtp != decimalwc)
+             /* Round up.  */
+             (*wtp)++;
+-          else if (__builtin_expect (spec == 'g' && type == 'f' && info->alt,
++          else if (__builtin_expect (spec == 'g' && type == 'f' && info->alt
++                                     && wtp == wstartp + 1
++                                     && wstartp[0] == L'0',
+                                      0))
+             /* This is a special case: the rounded number is 1.0,
+                the format is 'g' or 'G', and the alternative format
+--- libc/stdio-common/tfformat.c       30 Apr 2007 22:31:36 -0000      1.10
++++ libc/stdio-common/tfformat.c       31 Jul 2007 12:32:17 -0000      1.12
+@@ -4024,6 +4024,21 @@ sprint_double_type sprint_doubles[] =
+   {__LINE__, 1.0,                     "1.000000e+00", "%e"},
+   {__LINE__, .9999999999999999,               "1.000000e+00", "%e"},
++  {__LINE__, 912.98,                  "913.0", "%#.4g"},
++  {__LINE__, 50.999999,                       "51.000", "%#.5g"},
++  {__LINE__, 0.956,                   "1", "%.1g"},
++  {__LINE__, 0.956,                   "1.", "%#.1g"},
++  {__LINE__, 0.996,                   "1", "%.2g"},
++  {__LINE__, 0.996,                   "1.0", "%#.2g"},
++  {__LINE__, 999.98,                  "1000", "%.4g"},
++  {__LINE__, 999.98,                  "1000.", "%#.4g"},
++  {__LINE__, 999.998,                 "1000", "%.5g"},
++  {__LINE__, 999.998,                 "1000.0", "%#.5g"},
++  {__LINE__, 999.9998,                        "1000", "%g"},
++  {__LINE__, 999.9998,                        "1000.00", "%#g"},
++  {__LINE__, 912.98,                  "913", "%.4g"},
++  {__LINE__, 50.999999,                       "51", "%.5g"},
++
+   {0 }
+ };
diff --git a/src/patches/glibc/glibc-bz524.patch b/src/patches/glibc/glibc-bz524.patch
new file mode 100644 (file)
index 0000000..311f2f6
--- /dev/null
@@ -0,0 +1,18 @@
+2005-09-26  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #524]
+       * sysdeps/posix/getaddrinfo.c (match_prefix): Fix matching loop of
+       number of bits is multiple of 8.
+       Patch by Fredrik Tolf <fredrik@dolda2000.com>.
+
+--- libc/sysdeps/posix/getaddrinfo.c   18 May 2005 19:22:50 -0000      1.87
++++ libc/sysdeps/posix/getaddrinfo.c   26 Sep 2005 16:10:03 -0000      1.88
+@@ -1266,7 +1266,7 @@ match_prefix (const struct sockaddr_stor
+       uint8_t *mask = list[idx].prefix.s6_addr;
+       uint8_t *val = in6->sin6_addr.s6_addr;
+-      while (bits > 8)
++      while (bits >= 8)
+       {
+         if (*mask != *val)
+           break;
diff --git a/src/patches/glibc/glibc-bz5854.patch b/src/patches/glibc/glibc-bz5854.patch
new file mode 100644 (file)
index 0000000..d755cb5
--- /dev/null
@@ -0,0 +1,18 @@
+2008-03-03  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #5854]
+       * nis/ypclnt.c (yp_order): Fix handling of return value of
+       do_ypcall_tr call.
+       Patch by Jeff Moyer <jmoyer@redhat.com>.
+
+--- libc/nis/ypclnt.c  28 Apr 2006 16:59:22 -0000      1.58
++++ libc/nis/ypclnt.c  4 Mar 2008 00:27:41 -0000       1.59
+@@ -634,7 +634,7 @@ yp_order (const char *indomain, const ch
+                        (caddr_t) &req, (xdrproc_t) xdr_ypresp_order,
+                        (caddr_t) &resp);
+-  if (result == YPERR_SUCCESS)
++  if (result != YPERR_SUCCESS)
+     return result;
+   *outorder = resp.ordernum;
diff --git a/src/patches/glibc/glibc-bz644.patch b/src/patches/glibc/glibc-bz644.patch
new file mode 100644 (file)
index 0000000..3f3fa3e
--- /dev/null
@@ -0,0 +1,171 @@
+2005-09-26  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #644]
+       * sysdeps/posix/getaddrinfo.c (fls): New function.
+       (gaih_inet): Don't use ffs, use fls.  Convert address to native byte
+       order first.
+       * posix/Makefile (tests): Add tst-rfc3484.
+       * posix/tst-rfc3484.c: New file.
+
+--- libc/sysdeps/posix/getaddrinfo.c   26 Sep 2005 16:10:03 -0000      1.88
++++ libc/sysdeps/posix/getaddrinfo.c   26 Sep 2005 21:10:16 -0000      1.89
+@@ -1304,6 +1304,19 @@ get_precedence (const struct sockaddr_st
+ }
++/* Find last bit set in a word.  */
++static int
++fls (uint32_t a)
++{
++  uint32_t mask;
++  int n = 0;
++  for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
++    if ((a & mask) != 0)
++      break;
++  return n;
++}
++
++
+ static int
+ rfc3484_sort (const void *p1, const void *p2)
+ {
+@@ -1407,8 +1420,10 @@ rfc3484_sort (const void *p1, const void
+         in2_dst = (struct sockaddr_in *) a2->dest_addr->ai_addr;
+         in2_src = (struct sockaddr_in *) &a2->source_addr;
+-        bit1 = ffs (in1_dst->sin_addr.s_addr ^ in1_src->sin_addr.s_addr);
+-        bit2 = ffs (in2_dst->sin_addr.s_addr ^ in2_src->sin_addr.s_addr);
++        bit1 = fls (ntohl (in1_dst->sin_addr.s_addr
++                           ^ in1_src->sin_addr.s_addr));
++        bit2 = fls (ntohl (in2_dst->sin_addr.s_addr
++                           ^ in2_src->sin_addr.s_addr));
+       }
+       else if (a1->dest_addr->ai_family == PF_INET6)
+       {
+@@ -1435,10 +1450,10 @@ rfc3484_sort (const void *p1, const void
+         if (i < 4)
+           {
+-            bit1 = ffs (in1_dst->sin6_addr.s6_addr32[i]
+-                        ^ in1_src->sin6_addr.s6_addr32[i]);
+-            bit2 = ffs (in2_dst->sin6_addr.s6_addr32[i]
+-                        ^ in2_src->sin6_addr.s6_addr32[i]);
++            bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
++                               ^ in1_src->sin6_addr.s6_addr32[i]));
++            bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
++                               ^ in2_src->sin6_addr.s6_addr32[i]));
+           }
+       }
+--- libc/posix/Makefile        24 Jul 2005 21:39:12 -0000      1.185
++++ libc/posix/Makefile        26 Sep 2005 21:13:27 -0000      1.186
+@@ -87,7 +87,7 @@ tests                := tstgetopt testfnm runtests run
+                  tst-execvp1 tst-execvp2 tst-execlp1 tst-execlp2 \
+                  tst-execv1 tst-execv2 tst-execl1 tst-execl2 \
+                  tst-execve1 tst-execve2 tst-execle1 tst-execle2 \
+-                 tst-execvp3 tst-execvp4
++                 tst-execvp3 tst-execvp4 tst-rfc3484
+ xtests                := bug-ga2
+ ifeq (yes,$(build-shared))
+ test-srcs     := globtest
+--- libc/posix/tst-rfc3484.c 1 Jan 1970 00:00:00 -0000
++++ libc/posix/tst-rfc3484.c   26 Sep 2005 21:12:49 -0000      1.1
+@@ -0,0 +1,98 @@
++#include <stdbool.h>
++#include <stdio.h>
++
++/* Internal definitions used in the libc code.  */
++#define __getservbyname_r getservbyname_r
++#define __socket socket
++#define __getsockname getsockname
++#define __inet_aton inet_aton
++#define __gethostbyaddr_r gethostbyaddr_r
++#define __gethostbyname2_r gethostbyname2_r
++
++void
++attribute_hidden
++__check_pf (bool *p1, bool *p2)
++{
++  *p1 = *p2 = true;
++}
++int
++__idna_to_ascii_lz (const char *input, char **output, int flags)
++{
++  return 0;
++}
++int
++__idna_to_unicode_lzlz (const char *input, char **output, int flags)
++{
++  return 0;
++}
++
++#include "../sysdeps/posix/getaddrinfo.c"
++
++service_user *__nss_hosts_database attribute_hidden;
++
++
++/* This is the beginning of the real test code.  The above defines
++   (among other things) the function rfc3484_sort.  */
++
++
++#if __BYTE_ORDER == __BIG_ENDIAN
++# define h(n) n
++#else
++# define h(n) __bswap_constant_32 (n)
++#endif
++
++struct sockaddr_in addrs[] =
++{
++  { .sin_family = AF_INET, .sin_addr = { h (0xc0a86d1d) } },
++  { .sin_family = AF_INET, .sin_addr = { h (0xc0a85d03) } },
++  { .sin_family = AF_INET, .sin_addr = { h (0xc0a82c3d) } },
++  { .sin_family = AF_INET, .sin_addr = { h (0xc0a86002) } },
++  { .sin_family = AF_INET, .sin_addr = { h (0xc0a802f3) } },
++  { .sin_family = AF_INET, .sin_addr = { h (0xc0a80810) } },
++  { .sin_family = AF_INET, .sin_addr = { h (0xc0a85e02) } }
++};
++#define naddrs (sizeof (addrs) / sizeof (addrs[0]))
++static struct addrinfo ais[naddrs];
++static struct sort_result results[naddrs];
++
++static int expected[naddrs] =
++  {
++    6, 1, 0, 3, 2, 4, 5
++  };
++
++
++static int
++do_test (void)
++{
++  struct sockaddr_in so;
++  so.sin_family = AF_INET;
++  so.sin_addr.s_addr = h (0xc0a85f19);
++
++  for (int i = 0; i < naddrs; ++i)
++    {
++      ais[i].ai_family = AF_INET;
++      ais[i].ai_addr = (struct sockaddr *) &addrs[i];
++      results[i].dest_addr = &ais[i];
++      results[i].got_source_addr = true;
++      memcpy(&results[i].source_addr, &so, sizeof (so));
++      results[i].source_addr_len = sizeof (so);
++    }
++
++  qsort (results, naddrs, sizeof (results[0]), rfc3484_sort);
++
++  int result = 0;
++  for (int i = 0; i < naddrs; ++i)
++    {
++      struct in_addr addr = ((struct sockaddr_in *) (results[i].dest_addr->ai_addr))->sin_addr;
++
++      int here = memcmp (&addr, &addrs[expected[i]].sin_addr,
++                       sizeof (struct in_addr));
++      printf ("[%d] = %s: %s\n", i, inet_ntoa (addr), here ? "FAIL" : "OK");
++      result |= here;
++    }
++
++  return result;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-bz6461.patch b/src/patches/glibc/glibc-bz6461.patch
new file mode 100644 (file)
index 0000000..c5117c8
--- /dev/null
@@ -0,0 +1,39 @@
+2008-05-14  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #6461]
+       * iconv/gconv_simple.c (BODY for __gconv_transform_ascii_internal):
+       Add missing braces.
+       (BODY for __gconv_transform_internal_ascii): Likewise.
+
+--- libc/iconv/gconv_simple.c  12 Oct 2007 04:40:33 -0000      1.67
++++ libc/iconv/gconv_simple.c  14 May 2008 22:52:44 -0000      1.68
+@@ -820,9 +820,11 @@ ucs4le_internal_loop_single (struct __gc
+       STANDARD_FROM_LOOP_ERR_HANDLER (1);                                   \
+       }                                                                             \
+     else                                                                    \
+-      /* It's an one byte sequence.  */                                             \
+-      *((uint32_t *) outptr) = *inptr++;                                    \
+-      outptr += sizeof (uint32_t);                                          \
++      {                                                                             \
++      /* It's an one byte sequence.  */                                     \
++      *((uint32_t *) outptr) = *inptr++;                                    \
++      outptr += sizeof (uint32_t);                                          \
++      }                                                                             \
+   }
+ #define LOOP_NEED_FLAGS
+ #include <iconv/loop.c>
+@@ -851,9 +853,11 @@ ucs4le_internal_loop_single (struct __gc
+       STANDARD_TO_LOOP_ERR_HANDLER (4);                                     \
+       }                                                                             \
+     else                                                                    \
+-      /* It's an one byte sequence.  */                                             \
+-      *outptr++ = *((const uint32_t *) inptr);                                      \
+-      inptr += sizeof (uint32_t);                                           \
++      {                                                                             \
++      /* It's an one byte sequence.  */                                     \
++      *outptr++ = *((const uint32_t *) inptr);                              \
++      inptr += sizeof (uint32_t);                                           \
++      }                                                                             \
+   }
+ #define LOOP_NEED_FLAGS
+ #include <iconv/loop.c>
diff --git a/src/patches/glibc/glibc-bz6719.patch b/src/patches/glibc/glibc-bz6719.patch
new file mode 100644 (file)
index 0000000..adea77f
--- /dev/null
@@ -0,0 +1,69 @@
+2008-07-08  Ulrich Drepper  <drepper@redhat.com>
+
+       * stdio-common/Makefile: Add rules to build and run tst-setvbuf1.
+       * stdio-common/tst-setvbuf1.c: New file.
+       * stdio-common/tst-setvbuf1.expect: New file.
+
+       [BZ #6719]
+       * libio/iosetvbuf.c (_IO_setvbuf): Correctly clear buffering flags
+       when selecting fully-buffered stream.
+       Patch by Wang Xin <wxinee@gmail.com>.
+
+--- libc/libio/iosetvbuf.c     29 Aug 2003 19:58:27 -0000      1.20
++++ libc/libio/iosetvbuf.c     8 Jul 2008 16:20:32 -0000       1.21
+@@ -45,7 +45,7 @@ _IO_setvbuf (fp, buf, mode, size)
+   switch (mode)
+     {
+     case _IOFBF:
+-      fp->_IO_file_flags &= ~_IO_LINE_BUF|_IO_UNBUFFERED;
++      fp->_IO_file_flags &= ~(_IO_LINE_BUF|_IO_UNBUFFERED);
+       if (buf == NULL)
+       {
+         if (fp->_IO_buf_base == NULL)
+--- libc/stdio-common/Makefile 24 May 2008 18:14:36 -0000      1.112
++++ libc/stdio-common/Makefile 8 Jul 2008 16:32:28 -0000       1.113
+@@ -54,7 +54,8 @@ tests := tstscanf test_rdwr test-popen t
+        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 bug17 bug18 bug18a bug19 bug19a tst-popen2
++       tst-fwrite bug16 bug17 bug18 bug18a bug19 bug19a tst-popen2 \
++       tst-setvbuf1
+ test-srcs = tst-unbputc tst-printf
+@@ -101,3 +102,7 @@ bug15-ENV = LOCPATH=$(common-objpfx)loca
+ ifneq (,$(filter %REENTRANT, $(defines)))
+ CPPFLAGS += -D_IO_MTSAFE_IO
+ endif
++
++$(objpfx)tst-setvbuf1.out: tst-setvbuf1.expect $(objpfx)tst-setvbuf1
++      $(built-program-cmd) > $@ 2>&1
++      cmp tst-setvbuf1.expect $@
+--- libc/stdio-common/tst-setvbuf1.c   1 Jan 1970 00:00:00 -0000
++++ libc/stdio-common/tst-setvbuf1.c   8 Jul 2008 16:32:02 -0000       1.1
+@@ -0,0 +1,19 @@
++#include <stdio.h>
++
++static int
++do_test (void)
++{
++  if (setvbuf (stderr, NULL, _IOFBF, BUFSIZ) != 0)
++    {
++      puts ("Set full buffer error.");
++      return 1;
++    }
++
++  fprintf (stderr, "Output #1 <stderr>.\n");
++  printf ("Output #2 <stdout>.\n");
++
++  return 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/stdio-common/tst-setvbuf1.expect      1 Jan 1970 00:00:00 -0000
++++ libc/stdio-common/tst-setvbuf1.expect      8 Jul 2008 16:32:14 -0000       1.1
+@@ -0,0 +1,2 @@
++Output #2 <stdout>.
++Output #1 <stderr>.
diff --git a/src/patches/glibc/glibc-bz714.patch b/src/patches/glibc/glibc-bz714.patch
new file mode 100644 (file)
index 0000000..e107135
--- /dev/null
@@ -0,0 +1,107 @@
+2005-10-15  Ulrich Drepper  <drepper@redhat.com>
+
+       * wcsmbs/tst-mbrtowc2.c: Use de_DE.UTF-8 instead of en_US.UTF-8.
+       * wcsmbs/Makefile: Define tst-mbrtowc2-ENV.
+
+2005-09-25  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #714]
+       * iconv/loop.c [!STORE_REST] (SINGLE): Correctly record number of
+       left-over bytes and store them correctly.
+       * wcsmbs/tst-mbrtowc2.c: New file.
+       * wcsmbs/Makefile (tests): Add tst-mbrtowc2.
+
+--- libc/iconv/loop.c  11 Jun 2003 21:38:13 -0000      1.35
++++ libc/iconv/loop.c  25 Sep 2005 16:42:36 -0000      1.36
+@@ -450,6 +450,10 @@ SINGLE(LOOPFCT) (struct __gconv_step *st
+ #else
+       /* We don't have enough input for another complete input
+        character.  */
++      assert (inend - inptr > (state->__count & ~7));
++      assert (inend - inptr <= 7);
++      state->__count = (state->__count & ~7) | (inend - inptr);
++      inlen = 0;
+       while (inptr < inend)
+       state->__value.__wchb[inlen++] = *inptr++;
+ #endif
+--- libc/wcsmbs/tst-mbrtowc2.c 1 Jan 1970 00:00:00 -0000
++++ libc/wcsmbs/tst-mbrtowc2.c 15 Oct 2005 15:38:00 -0000      1.3
+@@ -0,0 +1,67 @@
++/* Derived from the test case in http://sourceware.org/bugzilla/show_bug.cgi?id=714 */
++#include <locale.h>
++#include <stdio.h>
++#include <string.h>
++#include <wchar.h>
++
++
++static struct
++{
++  const char *chp;
++  size_t nchp;
++  const char *loc;
++} tests[] =
++{
++  { (const char[]) { 0x8F, 0xA2, 0xAF }, 3, "ja_JP.EUC-JP" },
++  { (const char[]) { 0xD1, 0xA5 }, 2, "ja_JP.EUC-JP" },
++  { (const char[]) { 0x8E, 0xA5 }, 2, "ja_JP.EUC-JP" },
++  { (const char[]) { 0x8E, 0xA2, 0xA1, 0xA1 }, 4, "zh_TW.EUC-TW" },
++  { (const char[]) { 0xA1, 0xA1 }, 2, "zh_TW.EUC-TW" },
++  { (const char[]) { 0xE3, 0x80, 0x80 }, 3, "de_DE.UTF-8" },
++  { (const char[]) { 0xC3, 0xA4 }, 2, "de_DE.UTF-8" }
++};
++#define ntests (sizeof (tests) / sizeof (tests[0]))
++
++
++static int t (const char *ch, size_t nch, const char *loc);
++
++static int
++do_test (void)
++{
++  int r = 0;
++  for (int i = 0; i < ntests; ++i)
++    r |= t (tests[i].chp, tests[i].nchp, tests[i].loc);
++  return r;
++}
++
++static int
++t (const char *ch, size_t nch, const char *loc)
++{
++  int i;
++  wchar_t wch;
++  wchar_t wch2;
++  mbstate_t mbs;
++  int n = 0;
++
++  setlocale (LC_ALL, loc);
++
++  memset (&mbs, '\0', sizeof (mbstate_t));
++  for (i = 0; i < nch; i++)
++    {
++      n = mbrtowc (&wch, ch + i, 1, &mbs);
++      if (n >= 0)
++      break;
++    }
++  printf ("n = %d, count = %d, wch = %08lX\n", n, i, (unsigned long int) wch);
++
++  memset (&mbs, '\0', sizeof (mbstate_t));
++  n = mbrtowc (&wch2, ch, nch, &mbs);
++  printf ("n = %d, wch = %08lX\n", n, (unsigned long int) wch2);
++
++  int ret = n != nch || i + 1 != nch || n != nch || wch != wch2;
++  puts (ret ? "FAIL\n" : "OK\n");
++  return ret;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/wcsmbs/Makefile       24 Jul 2005 20:02:03 -0000      1.24
++++ libc/wcsmbs/Makefile       25 Sep 2005 16:57:58 -0000      1.25
+@@ -40,7 +40,7 @@ routines := wcscat wcschr wcscmp wcscpy 
+           wcsmbsload mbsrtowcs_l
+ tests := tst-wcstof wcsmbs-tst1 tst-wcsnlen tst-btowc tst-mbrtowc \
+-       tst-wcrtomb tst-wcpncpy tst-mbsrtowcs
++       tst-wcrtomb tst-wcpncpy tst-mbsrtowcs tst-mbrtowc2
+ include ../Rules
diff --git a/src/patches/glibc/glibc-bz968.patch b/src/patches/glibc/glibc-bz968.patch
new file mode 100644 (file)
index 0000000..69b37ae
--- /dev/null
@@ -0,0 +1,29 @@
+2005-10-15  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #968]
+       * string/strxfrm_l.c (STRXFRM): Fix exit conditions of two loops.
+
+--- libc/string/strxfrm_l.c    14 Mar 2004 20:52:47 -0000      1.4
++++ libc/string/strxfrm_l.c    15 Oct 2005 20:49:18 -0000      1.5
+@@ -210,8 +210,9 @@ STRXFRM (STRING_TYPE *dest, const STRING
+                     /* Handle the pushed elements now.  */
+                     size_t backw;
+-                    for (backw = idxcnt - 1; backw >= backw_stop; --backw)
++                    for (backw = idxcnt; backw > backw_stop; )
+                       {
++                        --backw;
+                         len = weights[idxarr[backw]++];
+                         if (needed + len < n)
+@@ -293,8 +294,9 @@ STRXFRM (STRING_TYPE *dest, const STRING
+                    /* Handle the pushed elements now.  */
+                     size_t backw;
+-                    for (backw = idxcnt - 1; backw >= backw_stop; --backw)
++                    for (backw = idxcnt; backw > backw_stop; )
+                       {
++                        --backw;
+                         len = weights[idxarr[backw]++];
+                         if (len != 0)
+                           {
diff --git a/src/patches/glibc/glibc-coverity.patch b/src/patches/glibc/glibc-coverity.patch
new file mode 100644 (file)
index 0000000..17d4251
--- /dev/null
@@ -0,0 +1,1608 @@
+2006-05-01  Ulrich Drepper  <drepper@redhat.com>
+
+       * misc/tsearch.c (__tdelete): Remove unnecessary test
+       [Coverity CID 75].
+
+       * sysdeps/generic/unwind-dw2.c (execute_cfa_program): Print error
+       message for invalid DWARF data instead of crashing.
+
+2006-04-08  Ulrich Drepper  <drepper@redhat.com>
+
+       * io/fts.c (fts_build): Call fts_lfree in the two error cases
+       after the loop [Coverity CID 187].
+
+       * nis/nis_getservlist.c (nis_getservlist): Also free lookup result
+       in error case [Coverity CID 189].
+
+       * nis/nis_getservlist.c (nis_getservlist): One more free call
+       needed [Coverity CID 190].
+
+2006-04-07  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/generic/unwind-dw2-fde.c (end_fde_sort): Remove
+       unnecessary test for accu->linear == NULL [Coverity CID 79].
+
+2006-04-07  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/posix/tempname.c (__gen_tempname): Change attempts_min
+       into a macro.  Use preprocessor to decide how to initialize
+       attempts [Coverity CID 67].
+
+       * io/fts.c (fts_build): Comment out dead code [Coverity CID 68].
+
+       * sunrpc/rpc_parse.c (def_union): Comment out dead code
+       [Coverity CID 70].
+
+       * locale/programs/linereader.c (lr_token): Remove duplicate
+       handling of EOF [Coverity CID 71].
+
+       * locale/programs/ld-numeric.c (numeric_read) [case tok_grouping]:
+       We bail out early if ignore_content is set, so there is no need to
+       check it later again [Coverity CID 72].
+
+       * inet/inet6_option.c (inet6_option_find): Check *tptrp for NULL,
+       not tptrp [Coverity CID 73].
+
+       * inet/inet6_option.c (inet6_option_next): Check *tptrp for NULL,
+       not tptrp [Coverity CID 74].
+
+       * misc/tsearch.c (__tsearch): Don't rotate tree if memory
+       allocation failed [Coverity CID 78].
+
+2006-04-07  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/generic/unwind-dw2.c (execute_cfa_program): Fix typo in
+       the last change.
+
+2006-04-07  Ulrich Drepper  <drepper@redhat.com>
+
+       * inet/rexec.c (rexec_af): If we have no canonical name don't
+       proceed further [Coverity CID 86].
+
+       * iconv/iconv_charmap.c (process_fd): Initialize inptr from inbuf,
+       not to NULL [Coverity CID 88].
+
+2006-04-06  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/generic/unwind-dw2.c (execute_cfa_program): Don't handle
+       DW_CFA_GNU_window_save if it obviously cannot work [Coverity CID 102].
+
+       * libio/fmemopen.c (fmemopen): Free stream memory in case of
+       invalid length [Coverity CID 106].
+
+       * nss/nss_files/files-key.c (search): Close stream before
+       successful return [Coverity CID 107].
+
+       * io/fts.c (fts_open): Don't allocate parent if *argv==NULL
+       [Coverity CID 108].
+
+       * sunrpc/rpc_cout.c (inline_struct): Free sizestr after use
+       [Coverity CID 110, 109].
+
+       * sunrpc/rpc_scan.c (docppline): Free file string if it is not
+       going to be used [Coverity CID 111].
+
+       * sysdeps/unix/sysv/linux/getsourcefilter.c (getsourcefilter): Free
+       memory if socket level value cannot be retrieved [Coverity CID 112].
+
+       * nis/nis_clone_dir.c (nis_clone_directory): Free all memory in
+       error case [Coverity CID 114].
+
+       * nis/nis_clone_res.c (nis_clone_result): Free all memory in the
+       error cases [Coverity CID 115].
+
+       * sunrpc/rpc_parse.c (get_definition): Free defp if tok ==
+       TOK_EOF [Coverity CID 116].
+
+       * sysdeps/unix/sysv/linux/setsourcefilter.c (setsourcefilter): Free
+       memory if socket level value cannot be retrieved [Coverity CID 117].
+
+       * elf/cache.c (save_cache): Initialize pad to avoid writing
+       uninitialized data to disk.
+
+       * elf/cache.c (save_cache): Free file_entries_new [Coverity CID 118].
+
+       * intl/finddomain.c (_nl_find_domain): Avoid strdup of expand
+       locale name, use strdupa.  Remove free call [Coverity CID 119].
+
+       * sunrpc/rpc_main.c (generate_guard): Avoid extra allocation and
+       the resulting leak [Coverity CID 121].
+
+       * sunrpc/rpc_main.c (mkfile_output): Free all allocated memory
+       [Coverity CID 122].
+
+       * sunrpc/rpc_main.c (h_output): Free guard after we are done
+       [Coverity CID 123].
+
+       * sunrpc/svc_udp.c (cache_set): Free victim if newbuf allocation
+       fails [Coverity CID 126].
+
+       * sunrpc/svc_udp.c (svcudp_enablecache): Free memory in error
+       cases [Coverity CID 127].
+
+       * nis/nis_table.c (__create_ib_request): Free ibreq in case strdup
+       fails [Coverity CID 128].
+
+       * nis/nis_getservlist.c (nis_getservlist): Free all memory in case
+       of an error [Coverity CID 130, 129].
+
+       * nis/nis_print_group_entry.c (nis_print_group_entry): If
+       nis_lookup call failed, return.  Free lookup result in error
+       cases [Coverity CID 131].
+
+       * nis/nis_removemember.c (nis_removemember): Free all memory in
+       error cases [Coverity CID 132].
+
+       * nis/nss_nisplus/nisplus-alias.c (_nss_nisplus_getaliasbyname_r):
+       Always free lookup result [Coverity CID 134].
+
+       * nis/nss_nisplus/nisplus-ethers.c (_nss_nisplus_gethostton_r):
+       Always free lookup result [Coverity CID 135].
+
+       * nis/nss_nisplus/nisplus-ethers.c (_nss_nisplus_getntohost_r):
+       Always free lookup result [Coverity CID 136].
+
+       * nis/nss_nisplus/nisplus-network.c (_nss_nisplus_getnetbyaddr_r):
+       Before retrying, free old result [Coverity CID 137].
+
+       * nis/nss_nisplus/nisplus-publickey.c (_nss_nisplus_netname2user):
+       Free res in case UID is zero [Coverity CID 138].
+
+       * nis/ypclnt.c (yp_update): Always free master string
+       [Coverity CID 140].
+
+       * nis/nis_creategroup.c (nis_creategroup): Free all memory in
+       error cases [Coverity CID 143, 142, 141].
+
+       * nis/nss_nis/nis-publickey.c (_nss_nis_getpublickey): Free result
+       if yp_match call succeeded [Coverity CID 155].
+
+       * nis/nss_nis/nis-publickey.c (_nss_nis_getsecretkey): Free string
+       allocated in yp_match at all times [Coverity CID 157, 156].
+
+       * nscd/nscd.c (write_pid): Close stream also if writing failed
+       [Coverity CID 165].
+
+       * nis/nis_table.c (nis_add_entry): Move test for NULL parameter
+       ahead of first use [Coverity CID 167].
+
+       * nis/nss_nis/nis-alias.c (_nss_nis_getaliasbyname_r): Move test
+       for NULL parameter ahead of first use [Coverity CID 168].
+
+       * intl/finddomain.c (_nl_find_domain): We never return NULL if we
+       found the locale [Coverity CID 169].
+
+       * inet/getnameinfo.c (getnameinfo): __getservbyport_r does not set
+       herrno [Coverity CID 178].
+
+       * nis/nis_checkpoint.c (nis_checkpoint): Don't access and returned
+       freed object [Coverity CID 182].
+nptl/
+2006-04-06  Ulrich Drepper  <drepper@redhat.com>
+
+       * pthread_getattr_np.c (pthread_getattr_np): Close fp if getrlimit
+       fails [Coverity CID 105].
+
+--- libc/elf/cache.c   4 Jan 2006 17:14:52 -0000       1.27
++++ libc/elf/cache.c   7 Apr 2006 03:36:30 -0000       1.28
+@@ -421,7 +420,7 @@ save_cache (const char *cache_name)
+   if (opt_format != 2)
+     {
+       if (write (fd, file_entries, file_entries_size)
+-        != (ssize_t)file_entries_size)
++        != (ssize_t) file_entries_size)
+       error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
+     }
+   if (opt_format != 0)
+@@ -430,15 +429,16 @@ save_cache (const char *cache_name)
+       if (opt_format != 2)
+       {
+         char zero[pad];
+-        if (write (fd, zero, pad) != (ssize_t)pad)
++        memset (zero, '\0', pad);
++        if (write (fd, zero, pad) != (ssize_t) pad)
+           error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
+       }
+       if (write (fd, file_entries_new, file_entries_new_size)
+-        != (ssize_t)file_entries_new_size)
++        != (ssize_t) file_entries_new_size)
+       error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
+     }
+-  if (write (fd, strings, total_strlen) != (ssize_t)total_strlen)
++  if (write (fd, strings, total_strlen) != (ssize_t) total_strlen)
+     error (EXIT_FAILURE, errno, _("Writing of cache data failed."));
+   close (fd);
+@@ -455,6 +455,7 @@ save_cache (const char *cache_name)
+          cache_name);
+   /* Free all allocated memory.  */
++  free (file_entries_new);
+   free (file_entries);
+   free (strings);
+--- libc/iconv/iconv_charmap.c 7 Dec 2005 05:47:27 -0000       1.4
++++ libc/iconv/iconv_charmap.c 7 Apr 2006 07:42:58 -0000       1.5
+@@ -488,7 +488,7 @@ process_fd (struct convtable *tbl, int f
+      process it in one step.  */
+   static char *inbuf = NULL;
+   static size_t maxlen = 0;
+-  char *inptr = NULL;
++  char *inptr = inbuf;
+   size_t actlen = 0;
+   while (actlen < maxlen)
+--- libc/inet/getnameinfo.c    17 Mar 2004 20:01:25 -0000      1.33
++++ libc/inet/getnameinfo.c    6 Apr 2006 21:51:24 -0000       1.34
+@@ -403,25 +403,16 @@ getnameinfo (const struct sockaddr *sa, 
+       if (!(flags & NI_NUMERICSERV))
+         {
+           struct servent *s, ts;
+-          while (__getservbyport_r (((const struct sockaddr_in *) sa)->sin_port,
+-                                    ((flags & NI_DGRAM) ? "udp" : "tcp"),
+-                                    &ts, tmpbuf, tmpbuflen, &s))
++          int e;
++          while ((e = __getservbyport_r (((const struct sockaddr_in *) sa)->sin_port,
++                                         ((flags & NI_DGRAM)
++                                          ? "udp" : "tcp"),
++                                         &ts, tmpbuf, tmpbuflen, &s)))
+             {
+-              if (herrno == NETDB_INTERNAL)
+-                {
+-                  if (errno == ERANGE)
+-                    tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
+-                                            2 * tmpbuflen);
+-                  else
+-                    {
+-                      __set_errno (serrno);
+-                      return EAI_SYSTEM;
+-                    }
+-                }
++              if (e == ERANGE)
++                tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
+               else
+-                {
+-                  break;
+-                }
++                break;
+             }
+           if (s)
+             {
+--- libc/inet/inet6_option.c   14 Jun 2003 08:43:24 -0000      1.2
++++ libc/inet/inet6_option.c   7 Apr 2006 18:24:19 -0000       1.4
+@@ -251,7 +251,7 @@ inet6_option_next (cmsg, tptrp)
+   const uint8_t *endp = CMSG_DATA (cmsg) + (ip6e->ip6e_len + 1) * 8;
+   const uint8_t *result;
+-  if (tptrp == NULL)
++  if (*tptrp == NULL)
+     /* This is the first call, return the first option if there is one.  */
+     result = (const uint8_t *) (ip6e + 1);
+   else
+@@ -308,7 +308,7 @@ inet6_option_find (cmsg, tptrp, type)
+   const uint8_t *endp = CMSG_DATA (cmsg) + (ip6e->ip6e_len + 1) * 8;
+   const uint8_t *next;
+-  if (tptrp == NULL)
++  if (*tptrp == NULL)
+     /* This is the first call, return the first option if there is one.  */
+     next = (const uint8_t *) (ip6e + 1);
+   else
+--- libc/inet/rexec.c  17 Feb 2005 01:15:44 -0000      1.24
++++ libc/inet/rexec.c  7 Apr 2006 08:08:51 -0000       1.25
+@@ -87,8 +87,11 @@ rexec_af(ahost, rport, name, pass, cmd, 
+                       return (-1);
+               }
+               *ahost = ahostbuf;
+-      } else
++      } else {
+               *ahost = NULL;
++              __set_errno (ENOENT);
++              return -1;
++      }
+       ruserpass(res0->ai_canonname, &name, &pass);
+ retry:
+       s = __socket(res0->ai_family, res0->ai_socktype, 0);
+--- libc/intl/finddomain.c     26 Sep 2004 04:30:40 -0000      1.33
++++ libc/intl/finddomain.c     7 Apr 2006 03:27:32 -0000       1.35
+@@ -110,7 +110,7 @@ _nl_find_domain (dirname, locale, domain
+           break;
+       }
+-      return cnt >= 0 ? retval : NULL;
++      return retval;
+       /* NOTREACHED */
+     }
+@@ -119,20 +119,7 @@ _nl_find_domain (dirname, locale, domain
+      done.  */
+   alias_value = _nl_expand_alias (locale);
+   if (alias_value != NULL)
+-    {
+-#if defined _LIBC || defined HAVE_STRDUP
+-      locale = strdup (alias_value);
+-      if (locale == NULL)
+-      return NULL;
+-#else
+-      size_t len = strlen (alias_value) + 1;
+-      locale = (char *) malloc (len);
+-      if (locale == NULL)
+-      return NULL;
+-
+-      memcpy (locale, alias_value, len);
+-#endif
+-    }
++    locale = strdupa (alias_value);
+   /* Now we determine the single parts of the locale name.  First
+      look for the language.  Termination symbols are `_' and `@' if
+@@ -169,10 +156,6 @@ _nl_find_domain (dirname, locale, domain
+       }
+     }
+-  /* The room for an alias was dynamically allocated.  Free it now.  */
+-  if (alias_value != NULL)
+-    free (locale);
+-
+   /* The space for normalized_codeset is dynamically allocated.  Free it.  */
+   if (mask & XPG_NORM_CODESET)
+     free ((void *) normalized_codeset);
+--- libc/io/fts.c      21 Dec 2005 08:33:31 -0000      1.31
++++ libc/io/fts.c      8 Apr 2006 19:33:17 -0000       1.34
+@@ -93,7 +93,8 @@ fts_open(argv, options, compar)
+       register FTS *sp;
+       register FTSENT *p, *root;
+       register int nitems;
+-      FTSENT *parent, *tmp;
++      FTSENT *parent = NULL;
++      FTSENT *tmp;
+       /* Options check. */
+       if (options & ~FTS_OPTIONMASK) {
+@@ -124,9 +125,11 @@ fts_open(argv, options, compar)
+               goto mem1;
+       /* Allocate/initialize root's parent. */
+-      if ((parent = fts_alloc(sp, "", 0)) == NULL)
+-              goto mem2;
+-      parent->fts_level = FTS_ROOTPARENTLEVEL;
++      if (*argv != NULL) {
++              if ((parent = fts_alloc(sp, "", 0)) == NULL)
++                      goto mem2;
++              parent->fts_level = FTS_ROOTPARENTLEVEL;
++        }
+       /* Allocate/initialize root(s). */
+       for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
+@@ -744,6 +747,10 @@ mem1:                             saved_errno = errno;
+                       p->fts_flags |= FTS_ISW;
+ #endif
++#if 0
++              /* Unreachable code.  cderrno is only ever set to a nonnull
++                 value if dirp is closed at the same time.  But then we
++                 cannot enter this loop.  */
+               if (cderrno) {
+                       if (nlinks) {
+                               p->fts_info = FTS_NS;
+@@ -751,7 +758,9 @@ mem1:                              saved_errno = errno;
+                       } else
+                               p->fts_info = FTS_NSOK;
+                       p->fts_accpath = cur->fts_accpath;
+-              } else if (nlinks == 0
++              } else
++#endif
++              if (nlinks == 0
+ #if defined DT_DIR && defined _DIRENT_HAVE_D_TYPE
+                          || (nostat &&
+                              dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
+@@ -819,6 +828,7 @@ mem1:                              saved_errno = errno;
+            fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
+               cur->fts_info = FTS_ERR;
+               SET(FTS_STOP);
++              fts_lfree(head);
+               return (NULL);
+       }
+@@ -826,6 +836,7 @@ mem1:                              saved_errno = errno;
+       if (!nitems) {
+               if (type == BREAD)
+                       cur->fts_info = FTS_DP;
++              fts_lfree(head);
+               return (NULL);
+       }
+--- libc/libio/fmemopen.c      23 Sep 2005 16:34:35 -0000      1.12
++++ libc/libio/fmemopen.c      7 Apr 2006 04:23:37 -0000       1.13
+@@ -202,7 +202,7 @@ fmemopen (void *buf, size_t len, const c
+   cookie_io_functions_t iof;
+   fmemopen_cookie_t *c;
+-  if (len == 0)
++  if (__builtin_expect (len == 0, 0))
+     {
+     einval:
+       __set_errno (EINVAL);
+@@ -227,8 +227,11 @@ fmemopen (void *buf, size_t len, const c
+     }
+   else
+     {
+-      if ((uintptr_t) len > -(uintptr_t) buf)
+-      goto einval;
++      if (__builtin_expect ((uintptr_t) len > -(uintptr_t) buf, 0))
++      {
++        free (c);
++        goto einval;
++      }
+       c->buffer = buf;
+     }
+--- libc/locale/programs/ld-numeric.c  7 Dec 2005 05:47:27 -0000       1.28
++++ libc/locale/programs/ld-numeric.c  7 Apr 2006 18:30:26 -0000       1.29
+@@ -302,7 +302,7 @@ numeric_read (struct linereader *ldfile,
+           {
+             size_t act = 0;
+             size_t max = 10;
+-            char *grouping = ignore_content ? NULL : xmalloc (max);
++            char *grouping = xmalloc (max);
+             do
+               {
+@@ -321,24 +321,20 @@ numeric_read (struct linereader *ldfile,
+                   }
+                 if (now->tok == tok_minus1)
+-                  {
+-                    if (!ignore_content)
+-                      grouping[act++] = '\177';
+-                  }
++                  grouping[act++] = '\177';
+                 else if (now->val.num == 0)
+                   {
+                     /* A value of 0 disables grouping from here on but
+                        we must not store a NUL character since this
+                        terminates the string.  Use something different
+                        which must not be used otherwise.  */
+-                    if (!ignore_content)
+-                      grouping[act++] = '\377';
++                    grouping[act++] = '\377';
+                   }
+                 else if (now->val.num > 126)
+                   lr_error (ldfile, _("\
+ %s: values for field `%s' must be smaller than 127"),
+                             "LC_NUMERIC", "grouping");
+-                else if (!ignore_content)
++                else
+                   grouping[act++] = now->val.num;
+                 /* Next must be semicolon.  */
+@@ -353,13 +349,10 @@ numeric_read (struct linereader *ldfile,
+             if (now->tok != tok_eol)
+               goto err_label;
+-            if (!ignore_content)
+-              {
+-                grouping[act++] = '\0';
++            grouping[act++] = '\0';
+-                numeric->grouping = xrealloc (grouping, act);
+-                numeric->grouping_len = act;
+-              }
++            numeric->grouping = xrealloc (grouping, act);
++            numeric->grouping_len = act;
+           }
+         break;
+--- libc/locale/programs/linereader.c  7 Dec 2005 05:47:27 -0000       1.32
++++ libc/locale/programs/linereader.c  7 Apr 2006 18:33:17 -0000       1.33
+@@ -214,12 +214,6 @@ lr_token (struct linereader *lr, const s
+       }
+       while (isspace (ch));
+-      if (ch == EOF)
+-      {
+-        lr->token.tok = tok_eof;
+-        return &lr->token;
+-      };
+-
+       if (ch != lr->comment_char)
+       break;
+--- libc/misc/tsearch.c        6 Jul 2001 04:55:36 -0000       1.11
++++ libc/misc/tsearch.c        2 May 2006 00:48:29 -0000       1.13
+@@ -285,11 +285,12 @@ __tsearch (const void *key, void **vroot
+       q->key = key;                   /* initialize new node */
+       q->red = 1;
+       q->left = q->right = NULL;
++
++      if (nextp != rootp)
++      /* There may be two red edges in a row now, which we must avoid by
++         rotating the tree.  */
++      maybe_split_for_insert (nextp, rootp, parentp, r, p_r, 1);
+     }
+-  if (nextp != rootp)
+-    /* There may be two red edges in a row now, which we must avoid by
+-       rotating the tree.  */
+-    maybe_split_for_insert (nextp, rootp, parentp, r, p_r, 1);
+   return q;
+ }
+@@ -446,7 +447,7 @@ __tdelete (const void *key, void **vroot
+             /* Q is R's brother, P is R's parent.  The subtree with root
+                R has one black edge less than the subtree with root Q.  */
+             q = p->right;
+-            if (q != NULL && q->red)
++            if (q->red)
+               {
+                 /* If Q is red, we know that P is black. We rotate P left
+                    so that Q becomes the top node in the tree, with P below
+@@ -534,7 +535,7 @@ __tdelete (const void *key, void **vroot
+           {
+             /* Comments: see above.  */
+             q = p->left;
+-            if (q != NULL && q->red)
++            if (q->red)
+               {
+                 q->red = 0;
+                 p->red = 1;
+--- libc/nis/nis_checkpoint.c  6 Jul 2001 04:55:36 -0000       1.10
++++ libc/nis/nis_checkpoint.c  6 Apr 2006 21:23:46 -0000       1.11
+@@ -24,7 +24,7 @@
+ #include "nis_intern.h"
+ nis_result *
+-nis_checkpoint(const_nis_name dirname)
++nis_checkpoint (const_nis_name dirname)
+ {
+   nis_result *res;
+@@ -48,7 +48,6 @@ nis_checkpoint(const_nis_name dirname)
+       if (__type_of (NIS_RES_OBJECT (res2)) != NIS_DIRECTORY_OBJ)
+       {
+         nis_freeresult (res2);
+-        nis_freeresult (res);
+         NIS_RES_STATUS (res) = NIS_INVALIDOBJ;
+         return res;
+       }
+--- libc/nis/nis_clone_dir.c   17 Feb 2005 01:17:24 -0000      1.4
++++ libc/nis/nis_clone_dir.c   7 Apr 2006 03:53:09 -0000       1.5
+@@ -29,15 +29,24 @@ nis_clone_directory (const directory_obj
+   char *addr;
+   unsigned int size;
+   XDR xdrs;
+-  directory_obj *res;
+   if (src == NULL)
+-    return (NULL);
++    return NULL;
+   size = xdr_sizeof ((xdrproc_t)_xdr_directory_obj, (char *)src);
+   if ((addr = calloc(1, size)) == NULL)
+     return NULL;
++  xdrmem_create(&xdrs, addr, size, XDR_ENCODE);
++  if (!_xdr_directory_obj (&xdrs, (directory_obj *)src))
++    {
++      xdr_destroy (&xdrs);
++      free (addr);
++      return NULL;
++    }
++  xdr_destroy (&xdrs);
++
++  directory_obj *res;
+   if (dest == NULL)
+     {
+       if ((res = calloc (1, sizeof (directory_obj))) == NULL)
+@@ -49,18 +58,12 @@ nis_clone_directory (const directory_obj
+   else
+     res = dest;
+-  xdrmem_create(&xdrs, addr, size, XDR_ENCODE);
+-  if (!_xdr_directory_obj (&xdrs, (directory_obj *)src))
+-    {
+-      xdr_destroy (&xdrs);
+-      free (addr);
+-      return NULL;
+-    }
+-  xdr_destroy (&xdrs);
+   xdrmem_create (&xdrs, addr, size, XDR_DECODE);
+   if (!_xdr_directory_obj (&xdrs, res))
+     {
+       xdr_destroy (&xdrs);
++      if (res != dest)
++      free (res);
+       free (addr);
+       return NULL;
+     }
+--- libc/nis/nis_clone_res.c   17 Feb 2005 01:17:24 -0000      1.4
++++ libc/nis/nis_clone_res.c   7 Apr 2006 03:51:17 -0000       1.6
+@@ -29,7 +29,6 @@ nis_clone_result (const nis_result *src,
+   char *addr;
+   unsigned int size;
+   XDR xdrs;
+-  nis_result *res;
+   if (src == NULL)
+     return (NULL);
+@@ -38,6 +37,16 @@ nis_clone_result (const nis_result *src,
+   if ((addr = calloc(1, size)) == NULL)
+     return NULL;
++  xdrmem_create (&xdrs, addr, size, XDR_ENCODE);
++  if (!_xdr_nis_result (&xdrs, (nis_result *)src))
++    {
++      xdr_destroy (&xdrs);
++      free (addr);
++      return NULL;
++    }
++  xdr_destroy (&xdrs);
++
++  nis_result *res;
+   if (dest == NULL)
+     {
+       if ((res = calloc (1, sizeof (nis_result))) == NULL)
+@@ -49,18 +58,12 @@ nis_clone_result (const nis_result *src,
+   else
+     res = dest;
+-  xdrmem_create(&xdrs, addr, size, XDR_ENCODE);
+-  if (!_xdr_nis_result (&xdrs, (nis_result *)src))
+-    {
+-      xdr_destroy (&xdrs);
+-      free (addr);
+-      return NULL;
+-    }
+-  xdr_destroy (&xdrs);
+-  xdrmem_create(&xdrs, addr, size, XDR_DECODE);
+-  if (!_xdr_nis_result(&xdrs, res))
++  xdrmem_create (&xdrs, addr, size, XDR_DECODE);
++  if (!_xdr_nis_result (&xdrs, res))
+     {
+       xdr_destroy (&xdrs);
++      if (res != dest)
++      free (res);
+       free (addr);
+       return NULL;
+     }
+--- libc/nis/nis_creategroup.c 6 Jul 2001 04:55:36 -0000       1.10
++++ libc/nis/nis_creategroup.c 6 Apr 2006 23:58:16 -0000       1.12
+@@ -46,7 +46,7 @@ nis_creategroup (const_nis_name group, u
+       else
+       return NIS_BADNAME;
+-      obj = malloc (sizeof (nis_object));
++      obj = calloc (1, sizeof (nis_object));
+       if (__builtin_expect (obj == NULL, 0))
+       return NIS_NOMEMORY;
+@@ -57,7 +57,13 @@ nis_creategroup (const_nis_name group, u
+       obj->zo_domain = strdup (domainbuf);
+       if (obj->zo_name == NULL || obj->zo_owner == NULL
+         || obj->zo_group == NULL || obj->zo_domain == NULL)
+-      return NIS_NOMEMORY;
++      {
++        free (obj->zo_group);
++        free (obj->zo_owner);
++        free (obj->zo_name);
++        free (obj);
++        return NIS_NOMEMORY;
++      }
+       obj->zo_access = __nis_default_access (NULL, 0);
+       obj->zo_ttl = 60 * 60;
+       obj->zo_data.zo_type = NIS_GROUP_OBJ;
+@@ -66,11 +72,11 @@ nis_creategroup (const_nis_name group, u
+       obj->zo_data.objdata_u.gr_data.gr_members.gr_members_val = NULL;
+       res = nis_add (buf, obj);
++      nis_free_object (obj);
+       if (res == NULL)
+       return NIS_NOMEMORY;
+       status = NIS_RES_STATUS (res);
+       nis_freeresult (res);
+-      nis_free_object (obj);
+       return status;
+     }
+--- libc/nis/nis_getservlist.c 6 Jul 2001 04:55:36 -0000       1.8
++++ libc/nis/nis_getservlist.c 8 Apr 2006 19:24:07 -0000       1.11
+@@ -40,7 +40,10 @@ nis_getservlist (const_nis_name dir)
+       malloc (sizeof (nis_server *) *
+               (NIS_RES_OBJECT (res)->DI_data.do_servers.do_servers_len + 1));
+       if (__builtin_expect (serv == NULL, 0))
+-      return NULL;
++      {
++        nis_freeresult (res);
++        return NULL;
++      }
+       for (i = 0; i < NIS_RES_OBJECT (res)->DI_data.do_servers.do_servers_len;
+          ++i)
+@@ -49,13 +52,41 @@ nis_getservlist (const_nis_name dir)
+           &NIS_RES_OBJECT (res)->DI_data.do_servers.do_servers_val[i];
+         serv[i] = calloc (1, sizeof (nis_server));
+         if (__builtin_expect (serv[i] == NULL, 0))
+-          return NULL;
++          {
++          free_all:
++            while (i-- > 0)
++              {
++                free (serv[i]->pkey.n_bytes);
++                if (serv[i]->ep.ep_val != NULL)
++                  {
++                    unsigned long int j;
++                    for (j = 0; j < serv[i]->ep.ep_len; ++j)
++                      {
++                        free (serv[i]->ep.ep_val[j].proto);
++                        free (serv[i]->ep.ep_val[j].family);
++                        free (serv[i]->ep.ep_val[j].uaddr);
++                      }
++                    free (serv[i]->ep.ep_val);
++                  }
++                free (serv[i]->name);
++                free (serv[i]);
++              }
++
++            free (serv);
++
++            nis_freeresult (res);
++
++            return NULL;
++          }
+         if (server->name != NULL)
+           {
+             serv[i]->name = strdup (server->name);
+             if (__builtin_expect (serv[i]->name == NULL, 0))
+-              return NULL;
++              {
++                ++i;
++                goto free_all;
++              }
+           }
+           serv[i]->ep.ep_len = server->ep.ep_len;
+@@ -66,7 +97,10 @@ nis_getservlist (const_nis_name dir)
+               serv[i]->ep.ep_val =
+               malloc (server->ep.ep_len * sizeof (endpoint));
+             if (__builtin_expect (serv[i]->ep.ep_val == NULL, 0))
+-              return NULL;
++              {
++                ++i;
++                goto free_all;
++              }
+               for (j = 0; j < serv[i]->ep.ep_len; ++j)
+                 {
+@@ -87,20 +121,20 @@ nis_getservlist (const_nis_name dir)
+                   serv[i]->ep.ep_val[j].proto = NULL;
+                 }
+             }
+-          else
+-          serv[i]->ep.ep_val = NULL;
++
+           serv[i]->key_type = server->key_type;
+           serv[i]->pkey.n_len = server->pkey.n_len;
+           if (server->pkey.n_len > 0)
+             {
+               serv[i]->pkey.n_bytes = malloc (server->pkey.n_len);
+               if (__builtin_expect (serv[i]->pkey.n_bytes == NULL, 0))
+-                return NULL;
++              {
++                ++i;
++                goto free_all;
++              }
+               memcpy (serv[i]->pkey.n_bytes, server->pkey.n_bytes,
+                       server->pkey.n_len);
+             }
+-          else
+-            serv[i]->pkey.n_bytes = NULL;
+         }
+       serv[i] = NULL;
+     }
+@@ -111,8 +145,7 @@ nis_getservlist (const_nis_name dir)
+       serv[0] = NULL;
+     }
+-  if (res != NULL)
+-    nis_freeresult (res);
++  nis_freeresult (res);
+   return serv;
+ }
+--- libc/nis/nis_print_group_entry.c   25 Mar 2004 03:51:53 -0000      1.9
++++ libc/nis/nis_print_group_entry.c   7 Apr 2006 00:39:14 -0000       1.10
+@@ -45,12 +45,16 @@ nis_print_group_entry (const_nis_name gr
+       }
+       res = nis_lookup (buf, FOLLOW_LINKS | EXPAND_NAME);
+-      if (NIS_RES_STATUS(res) != NIS_SUCCESS)
++      if (res == NULL)
+       return;
+-      if ((NIS_RES_NUMOBJ (res) != 1) ||
+-        (__type_of (NIS_RES_OBJECT (res)) != NIS_GROUP_OBJ))
+-      return;
++      if (NIS_RES_STATUS (res) != NIS_SUCCESS
++        || NIS_RES_NUMOBJ (res) != 1
++        || __type_of (NIS_RES_OBJECT (res)) != NIS_GROUP_OBJ)
++      {
++        nis_freeresult (res);
++        return;
++      }
+       char *mem_exp[NIS_RES_NUMOBJ (res)];
+       char *mem_imp[NIS_RES_NUMOBJ (res)];
+--- libc/nis/nis_removemember.c        29 Apr 2005 09:18:00 -0000      1.11
++++ libc/nis/nis_removemember.c        7 Apr 2006 00:34:55 -0000       1.12
+@@ -68,7 +68,10 @@ nis_removemember (const_nis_name member,
+       calloc (NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len,
+               sizeof (char *));
+       if (newmem == NULL)
+-      return NIS_NOMEMORY;
++      {
++        nis_freeresult (res);
++        return NIS_NOMEMORY;
++      }
+       k = NIS_RES_OBJECT (res)[0].GR_data.gr_members.gr_members_len;
+       j = 0;
+@@ -96,6 +99,7 @@ nis_removemember (const_nis_name member,
+       if (newp == NULL)
+       {
+         free (newmem);
++        nis_freeresult (res);
+         return NIS_NOMEMORY;
+       }
+       newmem = newp;
+--- libc/nis/nis_table.c       8 Dec 2005 04:11:05 -0000       1.30
++++ libc/nis/nis_table.c       7 Apr 2006 00:56:07 -0000       1.32
+@@ -41,7 +41,15 @@ __create_ib_request (const_nis_name name
+   /* Not of "[key=value,key=value,...],foo.." format? */
+   if (cptr[0] != '[')
+-    return (ibreq->ibr_name = strdup (cptr)) == NULL ? NULL : ibreq;
++    {
++      ibreq->ibr_name = strdup (cptr);
++      if (ibreq->ibr_name == NULL)
++      {
++        free (ibreq);
++        return NULL;
++      }
++      return ibreq;
++    }
+   /* "[key=value,...],foo" format */
+   ibreq->ibr_name = strchr (cptr, ']');
+@@ -497,15 +505,7 @@ libnsl_hidden_def (nis_list)
+ nis_result *
+ nis_add_entry (const_nis_name name, const nis_object *obj2, unsigned int flags)
+ {
+-  nis_object obj;
+-  nis_result *res;
+-  nis_error status;
+-  ib_request *ibreq;
+-  size_t namelen = strlen (name);
+-  char buf1[namelen + 20];
+-  char buf4[namelen + 20];
+-
+-  res = calloc (1, sizeof (nis_result));
++  nis_result *res = calloc (1, sizeof (nis_result));
+   if (res == NULL)
+     return NULL;
+@@ -515,12 +515,18 @@ nis_add_entry (const_nis_name name, cons
+       return res;
+     }
+-  if ((ibreq = __create_ib_request (name, flags)) == NULL)
++  size_t namelen = strlen (name);
++  char buf1[namelen + 20];
++  char buf4[namelen + 20];
++
++  ib_request *ibreq = __create_ib_request (name, flags);
++  if (ibreq == NULL)
+     {
+       NIS_RES_STATUS (res) = NIS_BADNAME;
+       return res;
+     }
++  nis_object obj;
+   memcpy (&obj, obj2, sizeof (nis_object));
+   if (obj.zo_name == NULL || strlen (obj.zo_name) == 0)
+@@ -543,11 +549,12 @@ nis_add_entry (const_nis_name name, cons
+     }
+   ibreq->ibr_obj.ibr_obj_len = 1;
+-  if ((status = __do_niscall (ibreq->ibr_name, NIS_IBADD,
+-                            (xdrproc_t) _xdr_ib_request,
+-                            (caddr_t) ibreq,
+-                            (xdrproc_t) _xdr_nis_result,
+-                            (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
++  nis_error status = __do_niscall (ibreq->ibr_name, NIS_IBADD,
++                                 (xdrproc_t) _xdr_ib_request,
++                                 (caddr_t) ibreq,
++                                 (xdrproc_t) _xdr_nis_result,
++                                 (caddr_t) res, 0, NULL);
++  if (status  != NIS_SUCCESS)
+     NIS_RES_STATUS (res) = status;
+   nis_free_request (ibreq);
+--- libc/nis/ypclnt.c  22 Feb 2006 10:02:50 -0000      1.56
++++ libc/nis/ypclnt.c  6 Apr 2006 23:59:35 -0000       1.57
+@@ -955,16 +955,22 @@ yp_update (char *domain, char *map, unsi
+   args.update_args.datum.yp_buf_len = datalen;
+   args.update_args.datum.yp_buf_val = data;
+-  if ((r = yp_master (domain, map, &master)) != 0)
++  if ((r = yp_master (domain, map, &master)) != YPERR_SUCCESS)
+     return r;
+   if (!host2netname (servername, master, domain))
+     {
+       fputs (_("yp_update: cannot convert host to netname\n"), stderr);
++      free (master);
+       return YPERR_YPERR;
+     }
+-  if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
++  clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp");
++
++  /* We do not need the string anymore.  */
++  free (master);
++
++  if (clnt == NULL)
+     {
+       clnt_pcreateerror ("yp_update: clnt_create");
+       return YPERR_RPC;
+--- libc/nis/nss_nis/nis-alias.c       16 Mar 2003 03:36:21 -0000      1.16
++++ libc/nis/nss_nis/nis-alias.c       6 Apr 2006 22:40:12 -0000       1.17
+@@ -206,32 +206,29 @@ enum nss_status
+ _nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias,
+                          char *buffer, size_t buflen, int *errnop)
+ {
+-  enum nss_status retval;
+-  int parse_res;
+-  char *domain;
+-  char *result;
+-  int len;
+-  char *p;
+-  size_t namlen = strlen (name);
+-  char name2[namlen + 1];
+-  size_t i;
+-
+   if (name == NULL)
+     {
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+     }
++  size_t namlen = strlen (name);
++  char name2[namlen + 1];
++
++  char *domain;
+   if (yp_get_default_domain (&domain))
+     return NSS_STATUS_UNAVAIL;
+   /* Convert name to lowercase.  */
++  size_t i;
+   for (i = 0; i < namlen; ++i)
+     name2[i] = _tolower (name[i]);
+   name2[i] = '\0';
+-  retval = yperr2nss (yp_match (domain, "mail.aliases", name2, namlen,
+-                              &result, &len));
++  char *result;
++  int len;
++  enum nss_status retval = yperr2nss (yp_match (domain, "mail.aliases", name2,
++                                              namlen, &result, &len));
+   if (retval != NSS_STATUS_SUCCESS)
+     {
+@@ -247,14 +244,15 @@ _nss_nis_getaliasbyname_r (const char *n
+       return NSS_STATUS_TRYAGAIN;
+     }
+-  p = strncpy (buffer, result, len);
++  char *p = strncpy (buffer, result, len);
+   buffer[len] = '\0';
+   while (isspace (*p))
+     ++p;
+   free (result);
+   alias->alias_local = 0;
+-  parse_res = _nss_nis_parse_aliasent (name, p, alias, buffer, buflen, errnop);
++  int parse_res = _nss_nis_parse_aliasent (name, p, alias, buffer, buflen,
++                                         errnop);
+   if (parse_res < 1)
+     {
+       if (parse_res == -1)
+--- libc/nis/nss_nis/nis-publickey.c   28 Oct 2005 22:38:59 -0000      1.14
++++ libc/nis/nss_nis/nis-publickey.c   6 Apr 2006 23:22:40 -0000       1.16
+@@ -73,6 +73,7 @@ _nss_nis_getpublickey (const char *netna
+       *p = 0;
+       strncpy (pkey, result, HEXKEYBYTES + 1);
+       pkey[HEXKEYBYTES] = '\0';
++      free (result);
+     }
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -115,20 +116,20 @@ _nss_nis_getsecretkey (const char *netna
+   if (result != NULL)
+     {
+       char *p = strchr (result, ':');
+-      if (p == NULL)
+-      return NSS_STATUS_SUCCESS;
+-
+-      ++p;
+-      strncpy (buf, p, 2 * (HEXKEYBYTES + 1));
+-      buf[2 * HEXKEYBYTES + 1] = '\0';
+-      if (!xdecrypt (buf, passwd))
+-      return NSS_STATUS_SUCCESS;
+-
+-      if (memcmp (buf, &(buf[HEXKEYBYTES]), KEYCHECKSUMSIZE) != 0)
+-      return NSS_STATUS_SUCCESS;
++      if (p != NULL)
++      {
++        ++p;
++        strncpy (buf, p, 2 * (HEXKEYBYTES + 1));
++        buf[2 * HEXKEYBYTES + 1] = '\0';
++        if (xdecrypt (buf, passwd)
++            && memcmp (buf, &(buf[HEXKEYBYTES]), KEYCHECKSUMSIZE) == 0)
++          {
++            buf[HEXKEYBYTES] = '\0';
++            strcpy (skey, buf);
++          }
++      }
+-      buf[HEXKEYBYTES] = '\0';
+-      strcpy (skey, buf);
++      free (result);
+     }
+   return NSS_STATUS_SUCCESS;
+ }
+--- libc/nis/nss_nisplus/nisplus-alias.c       25 Mar 2006 20:59:19 -0000      1.18
++++ libc/nis/nss_nisplus/nisplus-alias.c       7 Apr 2006 00:27:14 -0000       1.19
+@@ -304,10 +304,18 @@ _nss_nisplus_getaliasbyname_r (const cha
+     }
+   if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
+-    return niserr2nss (result->status);
++    {
++      enum nss_status status = niserr2nss (result->status);
++      nis_freeresult (result);
++      return status;
++    }
+   parse_res = _nss_nisplus_parse_aliasent (result, 0, alias,
+                                          buffer, buflen, errnop);
++
++  /* We do not need the lookup result anymore.  */
++  nis_freeresult (result);
++
+   if (__builtin_expect (parse_res < 1, 0))
+     {
+       __set_errno (olderr);
+--- libc/nis/nss_nisplus/nisplus-ethers.c      25 Mar 2006 20:59:19 -0000      1.22
++++ libc/nis/nss_nisplus/nisplus-ethers.c      7 Apr 2006 00:23:49 -0000       1.24
+@@ -261,17 +261,18 @@ _nss_nisplus_gethostton_r (const char *n
+   int parse_res = _nss_nisplus_parse_etherent (result, eth, buffer,
+                                              buflen, errnop);
++
++  /* We do not need the lookup result anymore.  */
++  nis_freeresult (result);
++
+   if (__builtin_expect (parse_res < 1, 0))
+     {
+       __set_errno (olderr);
+       if (parse_res == -1)
+-      {
+-        nis_freeresult (result);
+-        return NSS_STATUS_TRYAGAIN;
+-      }
+-      else
+-      return NSS_STATUS_NOTFOUND;
++      return NSS_STATUS_TRYAGAIN;
++
++      return NSS_STATUS_NOTFOUND;
+     }
+   return NSS_STATUS_SUCCESS;
+@@ -326,13 +327,14 @@ _nss_nisplus_getntohost_r (const struct 
+   int parse_res = _nss_nisplus_parse_etherent (result, eth, buffer,
+                                              buflen, errnop);
++
++  /* We do not need the lookup result anymore.  */
++  nis_freeresult (result);
++
+   if (__builtin_expect (parse_res < 1, 0))
+     {
+       if (parse_res == -1)
+-      {
+-        nis_freeresult (result);
+-        return NSS_STATUS_TRYAGAIN;
+-      }
++      return NSS_STATUS_TRYAGAIN;
+       return NSS_STATUS_NOTFOUND;
+     }
+--- libc/nis/nss_nisplus/nisplus-network.c     25 Mar 2006 20:59:19 -0000      1.22
++++ libc/nis/nss_nisplus/nisplus-network.c     7 Apr 2006 00:14:50 -0000       1.23
+@@ -443,6 +443,7 @@ _nss_nisplus_getnetbyaddr_r (uint32_t ad
+                  removed (one by one) */
+               buf2[b2len - 2] = '\0';
+               b2len -= 2;
++              nis_freeresult (result);
+               continue;
+             }
+--- libc/nis/nss_nisplus/nisplus-publickey.c   3 Dec 2005 22:08:17 -0000       1.17
++++ libc/nis/nss_nisplus/nisplus-publickey.c   7 Apr 2006 00:11:09 -0000       1.18
+@@ -394,6 +394,7 @@ _nss_nisplus_netname2user (char netname[
+   if (*uidp == 0)
+     {
+       syslog (LOG_ERR, _("netname2user: should not have uid 0"));
++      nis_freeresult (res);
+       return NSS_STATUS_NOTFOUND;
+     }
+--- libc/nptl/pthread_getattr_np.c     16 Apr 2004 23:49:09 -0000      1.11
++++ libc/nptl/pthread_getattr_np.c     7 Apr 2006 04:26:42 -0000       1.12
+@@ -83,51 +83,55 @@ pthread_getattr_np (thread_id, attr)
+       if (fp == NULL)
+       ret = errno;
+       /* We need the limit of the stack in any case.  */
+-      else if (getrlimit (RLIMIT_STACK, &rl) != 0)
+-      ret = errno;
+       else
+       {
+-        /* We need no locking.  */
+-        __fsetlocking (fp, FSETLOCKING_BYCALLER);
+-
+-        /* Until we found an entry (which should always be the case)
+-           mark the result as a failure.  */
+-        ret = ENOENT;
+-
+-        char *line = NULL;
+-        size_t linelen = 0;
+-        uintptr_t last_to = 0;
+-
+-        while (! feof_unlocked (fp))
++        if (getrlimit (RLIMIT_STACK, &rl) != 0)
++          ret = errno;
++        else
+           {
+-            if (__getdelim (&line, &linelen, '\n', fp) <= 0)
+-              break;
++            /* We need no locking.  */
++            __fsetlocking (fp, FSETLOCKING_BYCALLER);
+-            uintptr_t from;
+-            uintptr_t to;
+-            if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2)
+-              continue;
+-            if (from <= (uintptr_t) __libc_stack_end
+-                && (uintptr_t) __libc_stack_end < to)
++            /* Until we found an entry (which should always be the case)
++               mark the result as a failure.  */
++            ret = ENOENT;
++
++            char *line = NULL;
++            size_t linelen = 0;
++            uintptr_t last_to = 0;
++
++            while (! feof_unlocked (fp))
+               {
+-                /* Found the entry.  Now we have the info we need.  */
+-                iattr->stacksize = rl.rlim_cur;
+-                iattr->stackaddr = (void *) to;
+-
+-                /* The limit might be too high.  */
+-                if ((size_t) iattr->stacksize
+-                    > (size_t) iattr->stackaddr - last_to)
+-                  iattr->stacksize = (size_t) iattr->stackaddr - last_to;
+-
+-                /* We succeed and no need to look further.  */
+-                ret = 0;
+-                break;
++                if (__getdelim (&line, &linelen, '\n', fp) <= 0)
++                  break;
++
++                uintptr_t from;
++                uintptr_t to;
++                if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2)
++                  continue;
++                if (from <= (uintptr_t) __libc_stack_end
++                    && (uintptr_t) __libc_stack_end < to)
++                  {
++                    /* Found the entry.  Now we have the info we need.  */
++                    iattr->stacksize = rl.rlim_cur;
++                    iattr->stackaddr = (void *) to;
++
++                    /* The limit might be too high.  */
++                    if ((size_t) iattr->stacksize
++                        > (size_t) iattr->stackaddr - last_to)
++                      iattr->stacksize = (size_t) iattr->stackaddr - last_to;
++
++                    /* We succeed and no need to look further.  */
++                    ret = 0;
++                    break;
++                  }
++                last_to = to;
+               }
+-            last_to = to;
++
++            free (line);
+           }
+         fclose (fp);
+-        free (line);
+       }
+     }
+--- libc/nscd/nscd.c   1 Jan 2006 19:15:56 -0000       1.51
++++ libc/nscd/nscd.c   6 Apr 2006 22:55:50 -0000       1.52
+@@ -487,10 +487,10 @@ write_pid (const char *file)
+     return -1;
+   fprintf (fp, "%d\n", getpid ());
+-  if (fflush (fp) || ferror (fp))
+-    return -1;
++
++  int result = fflush (fp) || ferror (fp) ? -1 : 0;
+   fclose (fp);
+-  return 0;
++  return result;
+ }
+--- libc/nss/nss_files/files-key.c     6 Jul 2001 04:55:38 -0000       1.2
++++ libc/nss/nss_files/files-key.c     7 Apr 2006 04:19:55 -0000       1.3
+@@ -78,6 +78,7 @@ search (const char *netname, char *resul
+       p = __strtok_r (NULL, ":\n", &save_ptr);
+       if (p == NULL)  /* malformed line? */
+       continue;
++      fclose (stream);
+       strcpy (result, p);
+       return NSS_STATUS_SUCCESS;
+     }
+--- libc/sunrpc/rpc_cout.c     21 Nov 2005 15:43:03 -0000      1.15
++++ libc/sunrpc/rpc_cout.c     7 Apr 2006 04:08:05 -0000       1.16
+@@ -551,6 +551,7 @@ inline_struct (definition *def, int flag
+           }
+         size = 0;
+         i = 0;
++        free (sizestr);
+         sizestr = NULL;
+         print_stat (indent + 1, &dl->decl);
+       }
+--- libc/sunrpc/rpc_main.c     21 Nov 2005 15:43:03 -0000      1.26
++++ libc/sunrpc/rpc_main.c     7 Apr 2006 03:14:00 -0000       1.29
+@@ -531,7 +531,7 @@ generate_guard (const char *pathname)
+   filename = strrchr (pathname, '/'); /* find last component */
+   filename = ((filename == NULL) ? pathname : filename + 1);
+-  guard = strdup (filename);
++  guard = extendfile (filename, "_H_RPCGEN");
+   /* convert to upper case */
+   tmp = guard;
+   while (*tmp)
+@@ -541,7 +541,6 @@ generate_guard (const char *pathname)
+       tmp++;
+     }
+-  guard = extendfile (guard, "_H_RPCGEN");
+   return guard;
+ }
+@@ -661,6 +660,7 @@ h_output (const char *infile, const char
+     }
+   fprintf (fout, "\n#endif /* !_%s */\n", guard);
++  free (guard);
+   close_input ();
+   close_output (outfilename);
+ }
+@@ -946,6 +946,8 @@ clnt_output (const char *infile, const c
+   close_output (outfilename);
+ }
++static const char space[] = " ";
++
+ static char *
+ file_name (const char *file, const char *ext)
+ {
+@@ -954,16 +956,17 @@ file_name (const char *file, const char 
+   if (access (temp, F_OK) != -1)
+     return (temp);
+-  else
+-    return ((char *) " ");
++
++  free (temp);
++  return (char *) space;
+ }
+ static void
+ mkfile_output (struct commandline *cmd)
+ {
+   char *mkfilename;
+-  const char *clientname, *clntname, *xdrname, *hdrname;
+-  const char *servername, *svcname, *servprogname, *clntprogname;
++  char *clientname, *clntname, *xdrname, *hdrname;
++  char *servername, *svcname, *servprogname, *clntprogname;
+   svcname = file_name (cmd->infile, "_svc.c");
+   clntname = file_name (cmd->infile, "_clnt.c");
+@@ -977,8 +980,8 @@ mkfile_output (struct commandline *cmd)
+     }
+   else
+     {
+-      servername = " ";
+-      clientname = " ";
++      servername = (char *) space;
++      clientname = (char *) space;
+     }
+   servprogname = extendfile (cmd->infile, "_server");
+   clntprogname = extendfile (cmd->infile, "_client");
+@@ -988,6 +991,8 @@ mkfile_output (struct commandline *cmd)
+       char *cp, *temp;
+       mkfilename = alloc (strlen ("Makefile.") + strlen (cmd->infile) + 1);
++      if (mkfilename == NULL)
++      abort ();
+       temp = rindex (cmd->infile, '.');
+       cp = stpcpy (mkfilename, "Makefile.");
+       strncpy (cp, cmd->infile, (temp - cmd->infile));
+@@ -1046,6 +1051,23 @@ $(LDLIBS) \n\n");
+   f_print (fout, "clean:\n\t $(RM) core $(TARGETS) $(OBJECTS_CLNT) \
+ $(OBJECTS_SVC) $(CLIENT) $(SERVER)\n\n");
+   close_output (mkfilename);
++
++  free (clntprogname);
++  free (servprogname);
++  if (servername != space)
++    free (servername);
++  if (clientname != space)
++    free (clientname);
++  if (mkfilename != (char *) cmd->outfile)
++    free (mkfilename);
++  if (svcname != space)
++    free (svcname);
++  if (clntname != space)
++    free (clntname);
++  if (xdrname != space)
++    free (xdrname);
++  if (hdrname != space)
++    free (hdrname);
+ }
+ /*
+--- libc/sunrpc/rpc_parse.c    21 Nov 2005 15:43:03 -0000      1.9
++++ libc/sunrpc/rpc_parse.c    7 Apr 2006 18:36:30 -0000       1.11
+@@ -91,6 +91,7 @@ get_definition (void)
+       def_const (defp);
+       break;
+     case TOK_EOF:
++      free (defp);
+       return (NULL);
+     default:
+       error ("definition keyword expected");
+@@ -302,7 +303,9 @@ def_union (definition *defp)
+   case_list *cases;
+ /*  case_list *tcase; */
+   case_list **tailp;
++#if 0
+   int flag;
++#endif
+   defp->def_kind = DEF_UNION;
+   scan (TOK_IDENT, &tok);
+@@ -322,7 +325,9 @@ def_union (definition *defp)
+       cases->case_name = tok.str;
+       scan (TOK_COLON, &tok);
+       /* now peek at next token */
++#if 0
+       flag = 0;
++#endif
+       if (peekscan (TOK_CASE, &tok))
+       {
+@@ -339,6 +344,7 @@ def_union (definition *defp)
+           }
+         while (peekscan (TOK_CASE, &tok));
+       }
++#if 0
+       else if (flag)
+       {
+@@ -346,6 +352,7 @@ def_union (definition *defp)
+         tailp = &cases->next;
+         cases = ALLOC (case_list);
+       };
++#endif
+       get_declaration (&dec, DEF_UNION);
+       cases->case_decl = dec;
+--- libc/sunrpc/rpc_scan.c     21 Nov 2005 15:43:03 -0000      1.10
++++ libc/sunrpc/rpc_scan.c     7 Apr 2006 04:04:15 -0000       1.11
+@@ -535,6 +535,7 @@ docppline (const char *line, int *lineno
+   *p = 0;
+   if (*file == 0)
+     {
++      free (file);
+       *fname = NULL;
+     }
+   else
+--- libc/sunrpc/svc_udp.c      20 Jul 2005 17:50:28 -0000      1.23
++++ libc/sunrpc/svc_udp.c      7 Apr 2006 02:18:55 -0000       1.26
+@@ -485,6 +485,7 @@ svcudp_enablecache (SVCXPRT *transp, u_l
+   uc->uc_entries = ALLOC (cache_ptr, size * SPARSENESS);
+   if (uc->uc_entries == NULL)
+     {
++      mem_free (uc, sizeof (struct udp_cache));
+       CACHE_PERROR (_("enablecache: could not allocate cache data"));
+       return 0;
+     }
+@@ -492,6 +493,8 @@ svcudp_enablecache (SVCXPRT *transp, u_l
+   uc->uc_fifo = ALLOC (cache_ptr, size);
+   if (uc->uc_fifo == NULL)
+     {
++      mem_free (uc->uc_entries, size * SPARSENESS);
++      mem_free (uc, sizeof (struct udp_cache));
+       CACHE_PERROR (_("enablecache: could not allocate cache fifo"));
+       return 0;
+     }
+@@ -545,6 +548,7 @@ cache_set (SVCXPRT *xprt, u_long replyle
+       newbuf = mem_alloc (su->su_iosz);
+       if (newbuf == NULL)
+       {
++        mem_free (victim, sizeof (struct cache_node));
+         CACHE_PERROR (_("cache_set: could not allocate new rpc_buffer"));
+         return;
+       }
+--- libc/sysdeps/generic/unwind-dw2-fde.c      18 May 2004 21:18:52 -0000      1.7
++++ libc/sysdeps/generic/unwind-dw2-fde.c      7 Apr 2006 20:50:31 -0000       1.8
+@@ -595,7 +595,7 @@ end_fde_sort (struct object *ob, struct 
+ {
+   fde_compare_t fde_compare;
+-  if (accu->linear && accu->linear->count != count)
++  if (accu->linear->count != count)
+     abort ();
+   if (ob->s.b.mixed_encoding)
+--- libc/sysdeps/generic/unwind-dw2.c  21 Dec 2005 21:36:17 -0000      1.10
++++ libc/sysdeps/generic/unwind-dw2.c  2 May 2006 00:45:11 -0000       1.15
+@@ -25,6 +25,7 @@
+ #include <error.h>
+ #include <libintl.h>
+ #include <dwarf2.h>
++#include <stdio.h>
+ #include <unwind.h>
+ #include <unwind-pe.h>
+ #include <unwind-dw2-fde.h>
+@@ -837,9 +838,16 @@ execute_cfa_program (const unsigned char
+       case DW_CFA_restore_state:
+         {
+           struct frame_state_reg_info *old_rs = fs->regs.prev;
+-          fs->regs = *old_rs;
+-          old_rs->prev = unused_rs;
+-          unused_rs = old_rs;
++#ifdef _LIBC
++          if (old_rs == NULL)
++            __libc_fatal ("invalid DWARF unwind data");
++          else
++#endif
++            {
++              fs->regs = *old_rs;
++              old_rs->prev = unused_rs;
++              unused_rs = old_rs;
++            }
+         }
+         break;
+@@ -897,12 +905,16 @@ execute_cfa_program (const unsigned char
+         break;
+       case DW_CFA_GNU_window_save:
+-        /* ??? Hardcoded for SPARC register window configuration.  */
++        /* ??? Hardcoded for SPARC register window configuration.
++           At least do not do anything for archs which explicitly
++           define a lower register number.  */
++#if DWARF_FRAME_REGISTERS >= 32
+         for (reg = 16; reg < 32; ++reg)
+           {
+             fs->regs.reg[reg].how = REG_SAVED_OFFSET;
+             fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
+           }
++#endif
+         break;
+       case DW_CFA_GNU_args_size:
+--- libc/sysdeps/posix/tempname.c      27 Nov 2001 03:35:06 -0000      1.36
++++ libc/sysdeps/posix/tempname.c      7 Apr 2006 19:29:07 -0000       1.37
+@@ -242,11 +242,15 @@ __gen_tempname (char *tmpl, int kind)
+      necessary to try all these combinations.  Instead if a reasonable
+      number of names is tried (we define reasonable as 62**3) fail to
+      give the system administrator the chance to remove the problems.  */
+-  unsigned int attempts_min = 62 * 62 * 62;
++#define ATTEMPTS_MIN (62 * 62 * 62)
+   /* The number of times to attempt to generate a temporary file.  To
+      conform to POSIX, this must be no smaller than TMP_MAX.  */
+-  unsigned int attempts = attempts_min < TMP_MAX ? TMP_MAX : attempts_min;
++#if ATTEMPTS_MIN < TMP_MAX
++  unsigned int attempts = TMP_MAX;
++#else
++  unsigned int attempts = ATTEMPTS_MIN;
++#endif
+   len = strlen (tmpl);
+   if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
+--- libc/sysdeps/unix/sysv/linux/getsourcefilter.c     7 Aug 2004 18:21:41 -0000       1.7
++++ libc/sysdeps/unix/sysv/linux/getsourcefilter.c     7 Apr 2006 04:00:47 -0000       1.8
+@@ -112,23 +112,27 @@ getsourcefilter (int s, uint32_t interfa
+   gf->gf_numsrc = *numsrc;
+   /* We need to provide the appropriate socket level value.  */
++  int result;
+   int sol = __get_sol (group->sa_family, grouplen);
+   if (sol == -1)
+     {
+       __set_errno (EINVAL);
+-      return -1;
++      result = -1;
+     }
+-
+-  int result = __getsockopt (s, sol, MCAST_MSFILTER, gf, &needed);
+-
+-  /* If successful, copy the results to the places the caller wants
+-     them in.  */
+-  if (result == 0)
++  else
+     {
+-      *fmode = gf->gf_fmode;
+-      memcpy (slist, gf->gf_slist,
+-            MIN (*numsrc, gf->gf_numsrc) * sizeof (struct sockaddr_storage));
+-      *numsrc = gf->gf_numsrc;
++      result = __getsockopt (s, sol, MCAST_MSFILTER, gf, &needed);
++
++      /* If successful, copy the results to the places the caller wants
++       them in.  */
++      if (result == 0)
++      {
++        *fmode = gf->gf_fmode;
++        memcpy (slist, gf->gf_slist,
++                MIN (*numsrc, gf->gf_numsrc)
++                * sizeof (struct sockaddr_storage));
++        *numsrc = gf->gf_numsrc;
++      }
+     }
+   if (! use_alloca)
+--- libc/sysdeps/unix/sysv/linux/setsourcefilter.c     7 Aug 2004 18:21:41 -0000       1.5
++++ libc/sysdeps/unix/sysv/linux/setsourcefilter.c     7 Apr 2006 03:40:53 -0000       1.6
+@@ -57,14 +57,15 @@ setsourcefilter (int s, uint32_t interfa
+   memcpy (gf->gf_slist, slist, numsrc * sizeof (struct sockaddr_storage));
+   /* We need to provide the appropriate socket level value.  */
++  int result;
+   int sol = __get_sol (group->sa_family, grouplen);
+   if (sol == -1)
+     {
+       __set_errno (EINVAL);
+-      return -1;
++      result = -1;
+     }
+-
+-  int result = __setsockopt (s, sol, MCAST_MSFILTER, gf, needed);
++  else
++    result = __setsockopt (s, sol, MCAST_MSFILTER, gf, needed);
+   if (! use_alloca)
+     {
diff --git a/src/patches/glibc/glibc-coverity2.patch b/src/patches/glibc/glibc-coverity2.patch
new file mode 100644 (file)
index 0000000..b36bdf8
--- /dev/null
@@ -0,0 +1,854 @@
+2006-05-10  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/generic/wordexp.c (parse_glob): No need to check ifs for
+       NULL, the caller makes sure this is not the case.
+       (wordexp): Simplify ifs_white creation.  [Coverity CID 231]
+
+2006-05-09  Ulrich Drepper  <drepper@redhat.com>
+
+       * io/ftw.c (open_dir_stream): Return right away if REALLOC fails.
+       [Coverity CID 229, 230]
+
+       * argp/argp-help.c (hol_entry_help): Handle STATE==NULL in ARG and
+       DGETTEXT calls.
+       (hol_help): Likewise.  [Coverity CID 226, 227]
+
+       * nis/nis_creategroup.c (nis_creategroup): No need to duplicate
+       the return value of __nis_default_owner and __nis_default_group,
+       it has been especially allocated.  [Coverity CID 224]
+
+       * nis/nis_defaults.c (searchXYX): New functions.  Used by both
+       searchgroup and searchowner.  Significantly simplified.
+       (__nis_default_owner): Remove duplication.  Do not locally copy the
+       string before duplicating it.
+       (__nis_default_group): Likewise.
+
+       * nis/nis_lookup.c (nis_lookup): After calling nis_free_directory,
+       we must clear the variable before calling __nisfind_server.
+
+       * nis/nis_lookup.c (nis_lookup): Always free memory allocated with
+       nis_getnames.  [Coverity CID 223]
+
+       * locale/programs/locfile.c (locfile_read): Use alloca instead of
+       xmalloc to allocate local repertoire name.  [Coverity CID 222]
+
+       * iconv/iconv_charmap.c (use_to_charmap): No need to dynamically
+       allocate memory for the input to add_bytes.  [Coverity CID 221]
+
+       * sysdeps/generic/wordexp.c (w_addword): Free word if realloc fails
+       and it was allocated here.  [Coverity CID 219, 220]
+
+       * posix/getconf.c (print_all): Free confstr data after printing.
+       [Coverity CID 218]
+
+       * sysdeps/posix/getaddrinfo.c (gaih_inet): Free canon string if
+       list allocation fails.  [Coverity CID 215]
+
+       * nss/nsswitch.c (__nss_configure_lookup): Fix loop end condition.
+       [Coverity CID 213]
+
+       * argp/argp-help.c (hol_entry_cmp): Don't call canon_doc_option if
+       string is NULL.  [Coverity CID 212]
+       * argp/Makefile: Add rules to build and run bug-argp1.
+       * argp/bug-argp1.c: New file.
+
+       * elf/dl-dst.h (DL_DST_REQUIRED): Be prepared for missing link map
+       in statically linked code.
+       * elf/dl-load.c (_dl_dst_substitute): When replacing ORIGIN in
+       statically built code, be prepared to have no link map.
+       [Coverity CID 205]
+
+       * argp/argp-help.c (fill_in_uparams): Handle STATE==NULL in
+       dgettext calls. [Coverity CID 204]
+
+       * argp/argp-help.c (struct uparams): Remove valid member.  Change
+       the one user.
+       (uparam_names): Reduce size.  Avoid relative relocations.
+       Moved to read-only segment.
+       (fill_in_uparams): Update for new layout.
+
+       * argp/argp-help.c (hol_entry_help): Remove some dead code
+       [Coverity CID 200].
+
+--- libc/argp/Makefile 16 Sep 2003 05:46:38 -0000      1.6
++++ libc/argp/Makefile 9 May 2006 22:42:24 -0000       1.7
+@@ -26,10 +26,12 @@ distribute = argp-fmtstream.h argp-namef
+ routines      = $(addprefix argp-, ba fmtstream fs-xinl help parse pv \
+                                    pvh xinl eexst)
+-tests         = argp-test tst-argp1
++tests         = argp-test tst-argp1 bug-argp1
+ CFLAGS-argp-help.c = $(uses-callbacks) -fexceptions
+ CFLAGS-argp-parse.c = $(uses-callbacks)
+ CFLAGS-argp-fmtstream.c = -fexceptions
++bug-argp1-ARGS = -- --help
++
+ include ../Rules
+--- libc/argp/argp-help.c      9 Aug 2005 01:26:22 -0000       1.47
++++ libc/argp/argp-help.c      10 May 2006 06:28:06 -0000      1.54
+@@ -128,40 +128,37 @@ struct uparams
+   int header_col;
+   int usage_indent;
+   int rmargin;
+-
+-  int valid;                  /* True when the values in here are valid.  */
+ };
+ /* This is a global variable, as user options are only ever read once.  */
+ static struct uparams uparams = {
+   DUP_ARGS, DUP_ARGS_NOTE,
+   SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL,
+-  USAGE_INDENT, RMARGIN,
+-  0
++  USAGE_INDENT, RMARGIN
+ };
+ /* A particular uparam, and what the user name is.  */
+ struct uparam_name
+ {
+-  const char *name;           /* User name.  */
+-  int is_bool;                        /* Whether it's `boolean'.  */
+-  size_t uparams_offs;                /* Location of the (int) field in UPARAMS.  */
++  const char name[14];                /* User name.  */
++  bool is_bool;                       /* Whether it's `boolean'.  */
++  uint8_t uparams_offs;               /* Location of the (int) field in UPARAMS.  */
+ };
+ /* The name-field mappings we know about.  */
+ static const struct uparam_name uparam_names[] =
+ {
+-  { "dup-args",       1, offsetof (struct uparams, dup_args) },
+-  { "dup-args-note",  1, offsetof (struct uparams, dup_args_note) },
+-  { "short-opt-col",  0, offsetof (struct uparams, short_opt_col) },
+-  { "long-opt-col",   0, offsetof (struct uparams, long_opt_col) },
+-  { "doc-opt-col",    0, offsetof (struct uparams, doc_opt_col) },
+-  { "opt-doc-col",    0, offsetof (struct uparams, opt_doc_col) },
+-  { "header-col",     0, offsetof (struct uparams, header_col) },
+-  { "usage-indent",   0, offsetof (struct uparams, usage_indent) },
+-  { "rmargin",        0, offsetof (struct uparams, rmargin) },
+-  { 0 }
++  { "dup-args",       true, offsetof (struct uparams, dup_args) },
++  { "dup-args-note",  true, offsetof (struct uparams, dup_args_note) },
++  { "short-opt-col",  false, offsetof (struct uparams, short_opt_col) },
++  { "long-opt-col",   false, offsetof (struct uparams, long_opt_col) },
++  { "doc-opt-col",    false, offsetof (struct uparams, doc_opt_col) },
++  { "opt-doc-col",    false, offsetof (struct uparams, opt_doc_col) },
++  { "header-col",     false, offsetof (struct uparams, header_col) },
++  { "usage-indent",   false, offsetof (struct uparams, usage_indent) },
++  { "rmargin",        false, offsetof (struct uparams, rmargin) }
+ };
++#define nuparam_names (sizeof (uparam_names) / sizeof (uparam_names[0]))
+ /* Read user options from the environment, and fill in UPARAMS appropiately.  */
+ static void
+@@ -217,22 +214,27 @@ fill_in_uparams (const struct argp_state
+               SKIPWS (arg);
+             }
+-          for (un = uparam_names; un->name; un++)
++          un = uparam_names;
++          size_t u;
++          for (u = 0; u < nuparam_names; ++un, ++u)
+             if (strlen (un->name) == var_len
+                 && strncmp (var, un->name, var_len) == 0)
+               {
+                 if (unspec && !un->is_bool)
+                   __argp_failure (state, 0, 0,
+-                                  dgettext (state->root_argp->argp_domain, "\
++                                  dgettext (state == NULL ? NULL
++                                            : state->root_argp->argp_domain,
++                                            "\
+ %.*s: ARGP_HELP_FMT parameter requires a value"),
+                                   (int) var_len, var);
+                 else
+                   *(int *)((char *)&uparams + un->uparams_offs) = val;
+                 break;
+               }
+-          if (! un->name)
++          if (u == nuparam_names)
+             __argp_failure (state, 0, 0,
+-                            dgettext (state->root_argp->argp_domain, "\
++                            dgettext (state == NULL ? NULL
++                                      : state->root_argp->argp_domain, "\
+ %.*s: Unknown ARGP_HELP_FMT parameter"),
+                             (int) var_len, var);
+@@ -243,7 +245,8 @@ fill_in_uparams (const struct argp_state
+       else if (*var)
+         {
+           __argp_failure (state, 0, 0,
+-                          dgettext (state->root_argp->argp_domain,
++                          dgettext (state == NULL ? NULL
++                                    : state->root_argp->argp_domain,
+                                     "Garbage in ARGP_HELP_FMT: %s"), var);
+           break;
+         }
+@@ -759,9 +762,9 @@ hol_entry_cmp (const struct hol_entry *e
+       const char *long2 = hol_entry_first_long (entry2);
+       if (doc1)
+-      doc1 = canon_doc_option (&long1);
++      doc1 = long1 != NULL && canon_doc_option (&long1);
+       if (doc2)
+-      doc2 = canon_doc_option (&long2);
++      doc2 = long2 != NULL && canon_doc_option (&long2);
+       if (doc1 != doc2)
+       /* `documentation' options always follow normal options (or
+@@ -1102,7 +1105,9 @@ hol_entry_help (struct hol_entry *entry,
+           __argp_fmtstream_putc (stream, '-');
+           __argp_fmtstream_putc (stream, *so);
+           if (!have_long_opt || uparams.dup_args)
+-            arg (real, " %s", "[%s]", state->root_argp->argp_domain, stream);
++            arg (real, " %s", "[%s]",
++                 state == NULL ? NULL : state->root_argp->argp_domain,
++                 stream);
+           else if (real->arg)
+             hhstate->suppressed_dup_arg = 1;
+         }
+@@ -1122,26 +1127,22 @@ hol_entry_help (struct hol_entry *entry,
+              have been done on the original; but documentation options
+              should be pretty rare anyway...  */
+           __argp_fmtstream_puts (stream,
+-                                 dgettext (state->root_argp->argp_domain,
++                                 dgettext (state == NULL ? NULL
++                                           : state->root_argp->argp_domain,
+                                            opt->name));
+         }
+     }
+   else
+     /* A real long option.  */
+     {
+-      int first_long_opt = 1;
+-
+       __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col);
+       for (opt = real, num = entry->num; num > 0; opt++, num--)
+       if (opt->name && ovisible (opt))
+         {
+           comma (uparams.long_opt_col, &pest);
+           __argp_fmtstream_printf (stream, "--%s", opt->name);
+-          if (first_long_opt || uparams.dup_args)
+-            arg (real, "=%s", "[=%s]", state->root_argp->argp_domain,
+-                 stream);
+-          else if (real->arg)
+-            hhstate->suppressed_dup_arg = 1;
++          arg (real, "=%s", "[=%s]",
++               state == NULL ? NULL : state->root_argp->argp_domain, stream);
+         }
+     }
+@@ -1160,7 +1161,8 @@ hol_entry_help (struct hol_entry *entry,
+     }
+   else
+     {
+-      const char *tstr = real->doc ? dgettext (state->root_argp->argp_domain,
++      const char *tstr = real->doc ? dgettext (state == NULL ? NULL
++                                             : state->root_argp->argp_domain,
+                                              real->doc) : 0;
+       const char *fstr = filter_doc (tstr, real->key, entry->argp, state);
+       if (fstr && *fstr)
+@@ -1208,7 +1210,8 @@ hol_help (struct hol *hol, const struct 
+   if (hhstate.suppressed_dup_arg && uparams.dup_args_note)
+     {
+-      const char *tstr = dgettext (state->root_argp->argp_domain, "\
++      const char *tstr = dgettext (state == NULL ? NULL
++                                 : state->root_argp->argp_domain, "\
+ Mandatory or optional arguments to long options are also mandatory or \
+ optional for any corresponding short options.");
+       const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE,
+@@ -1555,8 +1558,7 @@ _help (const struct argp *argp, const st
+   __flockfile (stream);
+ #endif
+-  if (! uparams.valid)
+-    fill_in_uparams (state);
++  fill_in_uparams (state);
+   fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0);
+   if (! fs)
+--- libc/elf/dl-dst.h  6 Mar 2004 08:12:41 -0000       1.12
++++ libc/elf/dl-dst.h  9 May 2006 21:44:31 -0000       1.13
+@@ -50,6 +50,7 @@
+                                                                             \
+          First get the origin string if it is not available yet.            \
+          This can only happen for the map of the executable.  */            \
++      DL_DST_REQ_STATIC                                                     \
+       if ((l)->l_origin == NULL)                                            \
+         {                                                                   \
+           assert ((l)->l_name[0] == '\0');                                  \
+@@ -66,6 +67,18 @@
+                                                                             \
+     __len; })
++#ifdef SHARED
++# define DL_DST_REQ_STATIC /* nothing */
++#else
++# define DL_DST_REQ_STATIC \
++  if ((l) == NULL)                                                          \
++    {                                                                       \
++      const char *origin = _dl_get_origin ();                               \
++      origin_len = (origin && origin != (char *) -1 ? strlen (origin) : 0);   \
++    }                                                                       \
++  else
++#endif
++
+ #ifndef IS_IN_rtld
+ # define _dl_get_origin GLRO(dl_get_origin)
+ # define _dl_dst_substitute GLRO(dl_dst_substitute)
+--- libc/elf/dl-load.c 30 Apr 2006 23:46:13 -0000      1.275
++++ libc/elf/dl-load.c 9 May 2006 21:43:03 -0000       1.276
+@@ -266,7 +266,14 @@ _dl_dst_substitute (struct link_map *l, 
+         ++name;
+         if ((len = is_dst (start, name, "ORIGIN", is_path,
+                            INTUSE(__libc_enable_secure))) != 0)
+-          repl = l->l_origin;
++          {
++#ifndef SHARED
++            if (l == NULL)
++              repl = _dl_get_origin ();
++            else
++#endif
++              repl = l->l_origin;
++          }
+         else if ((len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0)
+           repl = GLRO(dl_platform);
+         else if ((len = is_dst (start, name, "LIB", is_path, 0)) != 0)
+--- libc/iconv/iconv_charmap.c 7 Apr 2006 07:42:58 -0000       1.5
++++ libc/iconv/iconv_charmap.c 10 May 2006 02:06:18 -0000      1.6
+@@ -365,19 +365,27 @@ use_to_charmap (const char *from_code, s
+         if (outptr != (char *) outbuf)
+           {
+             /* We got some output.  Good, use it.  */
+-            struct charseq *newp;
++            union
++            {
++              struct charseq seq;
++              struct
++              {
++                const char *name;
++                uint32_t ucs4;
++                int nbytes;
++                unsigned char bytes[outlen];
++              } mem;
++            } new;
+             outlen = sizeof (outbuf) - outlen;
+             assert ((char *) outbuf + outlen == outptr);
+-            newp = (struct charseq *) xmalloc (sizeof (struct charseq)
+-                                               + outlen);
+-            newp->name = out->name;
+-            newp->ucs4 = out->ucs4;
+-            newp->nbytes = outlen;
+-            memcpy (newp->bytes, outbuf, outlen);
++            new.mem.name = out->name;
++            new.mem.ucs4 = out->ucs4;
++            new.mem.nbytes = outlen;
++            memcpy (new.mem.bytes, outbuf, outlen);
+-            add_bytes (rettbl, newp, out);
++            add_bytes (rettbl, &new.seq, out);
+           }
+         /* Clear any possible state left behind.  */
+--- libc/io/ftw.c      2 Mar 2006 16:29:51 -0000       1.52
++++ libc/io/ftw.c      10 May 2006 06:35:59 -0000      1.53
+@@ -301,8 +301,7 @@ open_dir_stream (int *dfdp, struct ftw_d
+                     int save_err = errno;
+                     free (buf);
+                     __set_errno (save_err);
+-                    result = -1;
+-                    break;
++                    return -1;
+                   }
+                 buf = newp;
+               }
+--- libc/locale/programs/locfile.c     7 Dec 2005 05:47:27 -0000       1.38
++++ libc/locale/programs/locfile.c     10 May 2006 02:12:39 -0000      1.39
+@@ -155,10 +155,11 @@ argument to `%s' must be a single charac
+         if (repertoire_name == NULL)
+           {
+-            repertoire_name = memcpy (xmalloc (arg->val.str.lenmb + 1),
+-                                      arg->val.str.startmb,
+-                                      arg->val.str.lenmb);
+-            ((char *) repertoire_name)[arg->val.str.lenmb] = '\0';
++            char *newp = alloca (arg->val.str.lenmb + 1);
++
++            *((char *) mempcpy (newp, arg->val.str.startmb,
++                                arg->val.str.lenmb)) = '\0';
++            repertoire_name = newp;
+           }
+         break;
+--- libc/nis/nis_creategroup.c 6 Apr 2006 23:58:16 -0000       1.12
++++ libc/nis/nis_creategroup.c 10 May 2006 03:06:22 -0000      1.13
+@@ -52,8 +52,8 @@ nis_creategroup (const_nis_name group, u
+       obj->zo_oid.ctime = obj->zo_oid.mtime = time (NULL);
+       obj->zo_name = strdup (leafbuf);
+-      obj->zo_owner = strdup (__nis_default_owner (NULL));
+-      obj->zo_group = strdup (__nis_default_group (NULL));
++      obj->zo_owner = __nis_default_owner (NULL);
++      obj->zo_group = __nis_default_group (NULL);
+       obj->zo_domain = strdup (domainbuf);
+       if (obj->zo_name == NULL || obj->zo_owner == NULL
+         || obj->zo_group == NULL || obj->zo_domain == NULL)
+--- libc/nis/nis_defaults.c    24 Oct 2004 20:28:28 -0000      1.7
++++ libc/nis/nis_defaults.c    10 May 2006 02:54:46 -0000      1.8
+@@ -17,6 +17,7 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
++#include <assert.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -30,45 +31,36 @@
+ ** Some functions for parsing the -D param and NIS_DEFAULTS Environ
+ */
+ static nis_name
+-searchgroup (char *str)
++searchXYX (char *str, const char *what)
+ {
+-  char *cptr;
+-  int i;
++  assert (strlen (what) == 6);
++  assert (strncmp (str, what, 6) == 0);
++  str += 6;                   /* Points to the begin of the parameters.  */
++
++  int i = 0;
++  while (str[i] != '\0' && str[i] != ':')
++    ++i;
++  if (i == 0)                 /* only "<WHAT>=" ? */
++    return strdup ("");
+-  cptr = strstr (str, "group=");
+-  if (cptr == NULL)
+-    return NULL;
++  return strndup (str, i);
++}
+-  cptr += 6;                  /* points to the begin of the group string */
+-  i = 0;
+-  while (cptr[i] != '\0' && cptr[i] != ':')
+-    i++;
+-  if (i == 0)                 /* only "group=" ? */
+-    return (nis_name) "";
+-  return strndup (cptr, i);
++static nis_name
++searchgroup (char *str)
++{
++  return searchXYX (str, "group=");
+ }
++
+ static nis_name
+ searchowner (char *str)
+ {
+-  char *cptr;
+-  int i;
+-
+-  cptr = strstr (str, "owner=");
+-  if (cptr == NULL)
+-    return NULL;
+-
+-  cptr += 6;                  /* points to the begin of the owner string */
+-  i = 0;
+-  while (cptr[i] != '\0' && cptr[i] != ':')
+-    i++;
+-  if (i == 0)                 /* only "owner=" ? */
+-    return strdup ("");
+-
+-  return strndup (cptr, i);
++  return searchXYX (str, "owner=");
+ }
++
+ static uint32_t
+ searchttl (char *str)
+ {
+@@ -358,86 +350,61 @@ searchaccess (char *str, unsigned int ac
+   return result;
+ }
++
+ nis_name
+ __nis_default_owner (char *defaults)
+ {
+-  char default_owner[NIS_MAXNAMELEN + 1];
+-  char *cptr, *dptr;
++  char *default_owner = NULL;
+-  strcpy (default_owner, nis_local_principal ());
++  char *cptr = defaults;
++  if (cptr == NULL)
++    cptr = getenv ("NIS_DEFAULTS");
+-  if (defaults != NULL)
++  if (cptr != NULL)
+     {
+-      dptr = strstr (defaults, "owner=");
++      char *dptr = strstr (cptr, "owner=");
+       if (dptr != NULL)
+       {
+-        char *p = searchowner (defaults);
+-        if (strlen (p) <= NIS_MAXNAMELEN)
+-          strcpy (default_owner, p);
++        char *p = searchowner (dptr);
++        if (p == NULL)
++          return NULL;
++        default_owner = strdupa (p);
+         free (p);
+       }
+     }
+-  else
+-    {
+-      cptr = getenv ("NIS_DEFAULTS");
+-      if (cptr != NULL)
+-      {
+-        dptr = strstr (cptr, "owner=");
+-        if (dptr != NULL)
+-          {
+-            char *p = searchowner (cptr);
+-            if (strlen (p) <= NIS_MAXNAMELEN)
+-              strcpy (default_owner, p);
+-            free (p);
+-          }
+-      }
+-    }
+-  return strdup (default_owner);
++  return strdup (default_owner ?: nis_local_principal ());
+ }
+ libnsl_hidden_def (__nis_default_owner)
++
+ nis_name
+ __nis_default_group (char *defaults)
+ {
+-  char default_group[NIS_MAXNAMELEN + 1];
+-  char *cptr, *dptr;
++  char *default_group = NULL;
+-  strcpy (default_group, nis_local_group ());
++  char *cptr = defaults;
++  if (cptr == NULL)
++    cptr = getenv ("NIS_DEFAULTS");
+-  if (defaults != NULL)
++  if (cptr != NULL)
+     {
+-      dptr = strstr (defaults, "group=");
++      char *dptr = strstr (cptr, "group=");
+       if (dptr != NULL)
+       {
+-        char *p = searchgroup (defaults);
+-
+-        if (strlen (p) <= NIS_MAXNAMELEN)
+-          strcpy (default_group, p);
++        char *p = searchgroup (dptr);
++        if (p == NULL)
++          return NULL;
++        default_group = strdupa (p);
+         free (p);
+       }
+     }
+-  else
+-    {
+-      cptr = getenv ("NIS_DEFAULTS");
+-      if (cptr != NULL)
+-      {
+-        dptr = strstr (cptr, "group=");
+-        if (dptr != NULL)
+-          {
+-            char *p = searchgroup (cptr);
+-
+-            if (strlen (p) <= NIS_MAXNAMELEN)
+-              strcpy (default_group, p);
+-            free (p);
+-          }
+-      }
+-    }
+-  return strdup (default_group);
++  return strdup (default_group ?: nis_local_group ());
+ }
+ libnsl_hidden_def (__nis_default_group)
++
+ uint32_t
+ __nis_default_ttl (char *defaults)
+ {
+--- libc/nis/nis_lookup.c      8 Dec 2005 20:19:11 -0000       1.16
++++ libc/nis/nis_lookup.c      10 May 2006 02:30:20 -0000      1.18
+@@ -65,7 +65,7 @@ nis_lookup (const_nis_name name, const u
+       if (status != NIS_SUCCESS)
+       {
+         NIS_RES_STATUS (res) = status;
+-        return res;
++        goto out;
+       }
+       status = __nisbind_create (&bptr, dir->do_servers.do_servers_val,
+@@ -74,7 +74,7 @@ nis_lookup (const_nis_name name, const u
+       {
+         NIS_RES_STATUS (res) = status;
+         nis_free_directory (dir);
+-        return res;
++        goto out;;
+       }
+       while (__nisbind_connect (&bptr) != NIS_SUCCESS)
+@@ -83,7 +83,7 @@ nis_lookup (const_nis_name name, const u
+           {
+             nis_free_directory (dir);
+             NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
+-            return res;
++            goto out;
+           }
+       }
+@@ -121,8 +121,21 @@ nis_lookup (const_nis_name name, const u
+                       req.ns_name =
+                         strdup (NIS_RES_OBJECT (res)->LI_data.li_name);
+                       if (req.ns_name == NULL)
+-                        return NULL;
++                        {
++                          nis_free_directory (dir);
++                          res = NULL;
++                          goto out;
++                        }
++                      /* The following is a non-obvious optimization.  A
++                         nis_freeresult call would call xdr_free as the
++                         following code.  But it also would unnecessarily
++                         free the result structure.  We avoid this here
++                         along with the necessary tests.  */
++#if 1
++                      xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res);
++                      memset (res, '\0', sizeof (*res));
++#else
+                       nis_freeresult (res);
+                       res = calloc (1, sizeof (nis_result));
+                       if (res == NULL)
+@@ -130,6 +143,7 @@ nis_lookup (const_nis_name name, const u
+                           __nisbind_destroy (&bptr);
+                           return NULL;
+                         }
++#endif
+                       link_first_try = 1; /* Try at first the old binding */
+                       goto again;
+@@ -144,10 +158,12 @@ nis_lookup (const_nis_name name, const u
+                     {
+                       __nisbind_destroy (&bptr);
+                       nis_free_directory (dir);
++                      /* Otherwise __nisfind_server will not do anything.  */
++                      dir = NULL;
+                       if (__nisfind_server (req.ns_name, &dir)
+                           != NIS_SUCCESS)
+-                        return res;
++                        goto out;
+                       if (__nisbind_create (&bptr,
+                                             dir->do_servers.do_servers_val,
+@@ -155,7 +171,7 @@ nis_lookup (const_nis_name name, const u
+                                             flags) != NIS_SUCCESS)
+                         {
+                           nis_free_directory (dir);
+-                          return res;
++                          goto out;
+                         }
+                     }
+                   else
+@@ -167,7 +183,7 @@ nis_lookup (const_nis_name name, const u
+                       if (__nisbind_next (&bptr) != NIS_SUCCESS)
+                         {
+                           nis_free_directory (dir);
+-                          return res;
++                          goto out;
+                         }
+                     }
+                   goto again;
+@@ -184,7 +200,7 @@ nis_lookup (const_nis_name name, const u
+       if (status != NIS_SUCCESS)
+       {
+         NIS_RES_STATUS (res) = status;
+-        return res;
++        goto out;
+       }
+       switch (NIS_RES_STATUS (res))
+@@ -216,6 +232,7 @@ nis_lookup (const_nis_name name, const u
+       }
+     }
++ out:
+   if (names != namebuf)
+     nis_freenames (names);
+--- libc/nss/nsswitch.c        20 Dec 2005 18:41:01 -0000      1.61
++++ libc/nss/nsswitch.c        9 May 2006 22:46:57 -0000       1.63
+@@ -70,6 +70,7 @@ static const struct
+ #include "databases.def"
+ #undef DEFINE_DATABASE
+ };
++#define ndatabases (sizeof (databases) / sizeof (databases[0]))
+ __libc_lock_define_initialized (static, lock)
+@@ -211,7 +212,7 @@ __nss_configure_lookup (const char *dbna
+   service_user *new_db;
+   size_t cnt;
+-  for (cnt = 0; cnt < sizeof databases; ++cnt)
++  for (cnt = 0; cnt < ndatabases; ++cnt)
+     {
+       int cmp = strcmp (dbname, databases[cnt].name);
+       if (cmp == 0)
+@@ -223,7 +224,7 @@ __nss_configure_lookup (const char *dbna
+       }
+     }
+-  if (cnt == sizeof databases)
++  if (cnt == ndatabases)
+     {
+       __set_errno (EINVAL);
+       return -1;
+--- libc/posix/getconf.c       1 Jan 2006 19:15:55 -0000       1.42
++++ libc/posix/getconf.c       9 May 2006 23:58:22 -0000       1.43
+@@ -981,6 +981,7 @@ print_all (const char *path)
+         if (confstr (c->call_name, cvalue, clen) != clen)
+           error (3, errno, "confstr");
+         printf ("%.*s\n", (int) clen, cvalue);
++      free (cvalue);
+         break;
+     }
+   }
+--- libc/sysdeps/generic/wordexp.c     14 Dec 2005 12:02:26 -0000      1.48
++++ libc/sysdeps/generic/wordexp.c     10 May 2006 14:43:20 -0000      1.51
+@@ -166,6 +166,7 @@ w_addword (wordexp_t *pwordexp, char *wo
+   /* Add a word to the wordlist */
+   size_t num_p;
+   char **new_wordv;
++  bool allocated = false;
+   /* Internally, NULL acts like "".  Convert NULLs to "" before
+    * the caller sees them.
+@@ -175,6 +176,7 @@ w_addword (wordexp_t *pwordexp, char *wo
+       word = __strdup ("");
+       if (word == NULL)
+       goto no_space;
++      allocated = true;
+     }
+   num_p = 2 + pwordexp->we_wordc + pwordexp->we_offs;
+@@ -187,6 +189,9 @@ w_addword (wordexp_t *pwordexp, char *wo
+       return 0;
+     }
++  if (allocated)
++    free (word);
++
+ no_space:
+   return WRDE_NOSPACE;
+ }
+@@ -448,8 +453,7 @@ parse_glob (char **word, size_t *word_le
+   glob_list.we_offs = 0;
+   for (; words[*offset] != '\0'; ++*offset)
+     {
+-      if ((ifs && strchr (ifs, words[*offset])) ||
+-        (!ifs && strchr (" \t\n", words[*offset])))
++      if (strchr (ifs, words[*offset]) != NULL)
+       /* Reached IFS */
+       break;
+@@ -2273,18 +2272,15 @@ wordexp (const char *words, wordexp_t *p
+       char *ifsch = ifs;
+       char *whch = ifs_white;
+-      /* Start off with no whitespace IFS characters */
+-      ifs_white[0] = '\0';
+-
+       while (*ifsch != '\0')
+       {
+-        if ((*ifsch == ' ') || (*ifsch == '\t') || (*ifsch == '\n'))
++        if (*ifsch == ' ' || *ifsch == '\t' || *ifsch == '\n')
+           {
+             /* Whitespace IFS.  See first whether it is already in our
+                collection.  */
+             char *runp = ifs_white;
+-            while (runp < whch && *runp != '\0' && *runp != *ifsch)
++            while (runp < whch && *runp != *ifsch)
+               ++runp;
+             if (runp == whch)
+--- libc/sysdeps/posix/getaddrinfo.c   4 May 2006 06:31:25 -0000       1.101
++++ libc/sysdeps/posix/getaddrinfo.c   10 May 2006 06:40:34 -0000      1.103
+@@ -1047,7 +1047,10 @@ gaih_inet (const char *name, const struc
+           struct addrinfo *ai;
+           ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
+           if (ai == NULL)
+-            return -EAI_MEMORY;
++            {
++              free ((char *) canon);
++              return -EAI_MEMORY;
++            }
+           ai->ai_flags = req->ai_flags;
+           ai->ai_family = family;
+@@ -1065,6 +1068,10 @@ gaih_inet (const char *name, const struc
+ #endif /* _HAVE_SA_LEN */
+           ai->ai_addr->sa_family = family;
++          /* In case of an allocation error the list must be NULL
++             terminated.  */
++          ai->ai_next = NULL;
++
+           if (family == AF_INET6)
+             {
+               struct sockaddr_in6 *sin6p =
+@@ -1088,7 +1095,6 @@ gaih_inet (const char *name, const struc
+           pai = &(ai->ai_next);
+         }
+-      *pai = NULL;
+       ++*naddrs;
+--- libc/argp/bug-argp1.c      2006-04-19 19:21:31.748476000 +0200
++++ libc/argp/bug-argp1.c      2006-05-10 00:40:17.000000000 +0200
+@@ -0,0 +1,26 @@
++#include <argp.h>
++
++
++static const struct argp_option test_options[] =
++{
++  { NULL, 'a', NULL, OPTION_DOC, NULL },
++  { NULL, 'b', NULL, OPTION_DOC, NULL },
++  { NULL, 0, NULL, 0, NULL }
++};
++
++static struct argp test_argp =
++{
++  test_options
++};
++
++
++static int
++do_test (int argc, char *argv[])
++{
++  int i;
++  argp_parse (&test_argp, argc, argv, 0, &i, NULL);
++  return 0;
++}
++
++#define TEST_FUNCTION do_test (argc, argv)
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-csqrt.patch b/src/patches/glibc/glibc-csqrt.patch
new file mode 100644 (file)
index 0000000..ed5eaad
--- /dev/null
@@ -0,0 +1,69 @@
+2005-10-13  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1466]
+       * sysdeps/generic/s_csqrt.c (__csqrt): For zero real part, return
+       principal square root.
+       * sysdeps/generic/s_csqrtf.c (__csqrtf): Likewise.
+       * sysdeps/generic/s_csqrtl.c (__csqrtl): Likewise.
+       * math/libm-test.inc (csqrt_test): Add test for returning
+       principal value.
+--- libc/math/libm-test.inc    6 Jan 2005 21:49:23 -0000       1.65
++++ libc/math/libm-test.inc    13 Oct 2005 19:07:12 -0000      1.66
+@@ -153,6 +153,7 @@
+ #define M_PI2_LOG10El         M_PI_2l * M_LOG10El
+ #define M_PI4_LOG10El         M_PI_4l * M_LOG10El
+ #define M_PI_LOG10El          M_PIl * M_LOG10El
++#define M_SQRT_2_2            0.70710678118654752440084436210484903L /* sqrt (2) / 2 */
+ static FILE *ulps_file;       /* File to document difference.  */
+ static int output_ulps;       /* Should ulps printed?  */
+@@ -2212,6 +2213,9 @@ csqrt_test (void)
+   TEST_c_c (csqrt, 0.75L, 1.25L, 1.05065169626078392338656675760808326L, 0.594868882070379067881984030639932657L);
+   TEST_c_c (csqrt, -2, -3, 0.89597747612983812471573375529004348L, -1.6741492280355400404480393008490519L);
+   TEST_c_c (csqrt, -2, 3, 0.89597747612983812471573375529004348L, 1.6741492280355400404480393008490519L);
++  /* Principal square root should be returned (i.e., non-negative real
++     part).  */
++  TEST_c_c (csqrt, 0, -1, M_SQRT_2_2, -M_SQRT_2_2);
+   END (csqrt, complex);
+ }
+--- libc/sysdeps/generic/s_csqrt.c     6 Jul 2001 04:55:49 -0000       1.2
++++ libc/sysdeps/generic/s_csqrt.c     13 Oct 2005 19:05:44 -0000      1.3
+@@ -79,8 +79,8 @@ __csqrt (__complex__ double x)
+       {
+         double r = __ieee754_sqrt (0.5 * fabs (__imag__ x));
+-        __real__ res = __copysign (r, __imag__ x);
+-        __imag__ res = r;
++        __real__ res = r;
++        __imag__ res = __copysign (r, __imag__ x);
+       }
+       else
+       {
+--- libc/sysdeps/generic/s_csqrtf.c    13 Jan 2004 09:08:04 -0000      1.3
++++ libc/sysdeps/generic/s_csqrtf.c    13 Oct 2005 19:05:12 -0000      1.4
+@@ -79,8 +79,8 @@ __csqrtf (__complex__ float x)
+       {
+         float r = __ieee754_sqrtf (0.5 * fabsf (__imag__ x));
+-        __real__ res = __copysignf (r, __imag__ x);
+-        __imag__ res = r;
++        __real__ res = r;
++        __imag__ res = __copysignf (r, __imag__ x);
+       }
+       else
+       {
+--- libc/sysdeps/generic/s_csqrtl.c    6 Jul 2001 04:55:49 -0000       1.2
++++ libc/sysdeps/generic/s_csqrtl.c    13 Oct 2005 19:04:31 -0000      1.3
+@@ -79,8 +79,8 @@ __csqrtl (__complex__ long double x)
+       {
+         long double r = __ieee754_sqrtl (0.5 * fabsl (__imag__ x));
+-        __real__ res = __copysignl (r, __imag__ x);
+-        __imag__ res = r;
++        __real__ res = r;
++        __imag__ res = __copysignl (r, __imag__ x);
+       }
+       else
+       {
diff --git a/src/patches/glibc/glibc-ctermid.patch b/src/patches/glibc/glibc-ctermid.patch
new file mode 100644 (file)
index 0000000..11fe945
--- /dev/null
@@ -0,0 +1,15 @@
+2006-01-03  Jakub Jelinek  <jakub@redhat.com>
+
+       * posix/unistd.h (ctermid): Remove __nonnull attribute.
+
+--- libc/posix/unistd.h        16 Dec 2005 00:15:19 -0000      1.139
++++ libc/posix/unistd.h        3 Jan 2006 15:57:08 -0000       1.140
+@@ -1075,7 +1075,7 @@ extern void swab (__const void *__restri
+    It is also found in <stdio.h>.  */
+ #ifdef __USE_XOPEN
+ /* Return the name of the controlling terminal.  */
+-extern char *ctermid (char *__s) __THROW __nonnull ((1));
++extern char *ctermid (char *__s) __THROW;
+ #endif
diff --git a/src/patches/glibc/glibc-do_ypcall.patch b/src/patches/glibc/glibc-do_ypcall.patch
new file mode 100644 (file)
index 0000000..59145e6
--- /dev/null
@@ -0,0 +1,16 @@
+2005-11-26  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/ypclnt.c (do_ypcall): Check memory allocation suceeded before
+       calling yp_bind_ypbindprog.
+
+--- libc/nis/ypclnt.c  25 Nov 2005 16:04:44 -0000      1.52
++++ libc/nis/ypclnt.c  26 Nov 2005 22:16:03 -0000      1.53
+@@ -349,7 +349,7 @@ do_ypcall (const char *domain, u_long pr
+   if (status != YPERR_SUCCESS)
+     {
+       ydb = calloc (1, sizeof (dom_binding));
+-      if (yp_bind_ypbindprog (domain, ydb) == YPERR_SUCCESS)
++      if (ydb != NULL && yp_bind_ypbindprog (domain, ydb) == YPERR_SUCCESS)
+       {
+         status = __ypclnt_call (domain, prog, xargs, req, xres,
+                                 resp, &ydb, 1);
diff --git a/src/patches/glibc/glibc-doc-fixes.patch b/src/patches/glibc/glibc-doc-fixes.patch
new file mode 100644 (file)
index 0000000..50dcd05
--- /dev/null
@@ -0,0 +1,103 @@
+2006-02-03  Jakub Jelinek  <jakub@redhat.com>
+
+       * manual/filesys.texi (futimes): Fix prototype.
+
+2004-08-09  Paul Eggert  <eggert@cs.ucla.edu>
+
+       [BZ #315]
+       * manual/memory.texi (Obstacks Data Alignment): The default
+       alignment is not 4: it is enough to hold any type of data.
+       Problem reported by Benno in
+       <http://sources.redhat.com/ml/libc-alpha/2004-08/msg00055.html>.
+
+2006-02-03  Ulrich Drepper  <drepper@redhat.com>
+
+       * manual/stdio.texi (Formatted Output Functions): Fix make_message
+       example.  Patch by NIIBE Yutaka <gniibe@m17n.org>.
+
+2005-12-31  Andreas Jaeger  <aj@suse.de>
+
+       [BZ #1395]
+       * manual/filesys.texi (Symbolic Links): Fix description of
+       canonicalize_file_name based on patch by Oskar Liljeblad
+       <oskar@osk.mine.nu>.
+
+2005-12-15  Roland McGrath  <roland@redhat.com>
+
+       [BZ #1997]
+       * manual/stdio.texi (String Streams): For open_memstream, elaborate a
+       little on malloc reference.
+
+--- libc/manual/filesys.texi   15 Oct 2005 17:37:58 -0000      1.98
++++ libc/manual/filesys.texi   22 Feb 2006 07:17:46 -0000      1.100
+@@ -1250,10 +1250,10 @@ result is passed back as the return valu
+ memory allocated with @code{malloc}.  If the result is not used anymore
+ the memory should be freed with a call to @code{free}.
+-In any of the path components except the last one is missing the
+-function returns a NULL pointer.  This is also what is returned if the
+-length of the path reaches or exceeds @code{PATH_MAX} characters.  In
+-any case @code{errno} is set accordingly.
++If any of the path components is missing the function returns a NULL
++pointer.  This is also what is returned if the length of the path
++reaches or exceeds @code{PATH_MAX} characters.  In any case
++@code{errno} is set accordingly.
+ @table @code
+ @item ENAMETOOLONG
+@@ -2806,7 +2806,7 @@ function.
+ @comment sys/time.h
+ @comment BSD
+-@deftypefun int futimes (int *@var{fd}, struct timeval @var{tvp}@t{[2]})
++@deftypefun int futimes (int @var{fd}, struct timeval @var{tvp}@t{[2]})
+ This function is like @code{utimes}, except that it takes an open file
+ descriptor as an argument instead of a file name.  @xref{Low-Level
+ I/O}.  This function comes from FreeBSD, and is not available on all
+--- libc/manual/memory.texi    13 Sep 2005 17:46:01 -0000      1.80
++++ libc/manual/memory.texi    22 Feb 2006 06:57:59 -0000      1.81
+@@ -1968,7 +1968,8 @@ obstack_next_free (@var{obstack-ptr}) - 
+ Each obstack has an @dfn{alignment boundary}; each object allocated in
+ the obstack automatically starts on an address that is a multiple of the
+-specified boundary.  By default, this boundary is 4 bytes.
++specified boundary.  By default, this boundary is aligned so that
++the object can hold any type of data.
+ To access an obstack's alignment boundary, use the macro
+ @code{obstack_alignment_mask}, whose function prototype looks like
+@@ -1980,7 +1981,9 @@ this:
+ The value is a bit mask; a bit that is 1 indicates that the corresponding
+ bit in the address of an object should be 0.  The mask value should be one
+ less than a power of 2; the effect is that all object addresses are
+-multiples of that power of 2.  The default value of the mask is 3, so that
++multiples of that power of 2.  The default value of the mask is a value
++that allows aligned objects to hold any type of data: for example, if
++its value is 3, any type of data can be stored at locations whose
+ addresses are multiples of 4.  A mask value of 0 means an object can start
+ on any multiple of 1 (that is, no alignment is required).
+--- libc/manual/stdio.texi     25 Sep 2005 18:24:55 -0000      1.134
++++ libc/manual/stdio.texi     4 Feb 2006 07:12:54 -0000       1.136
+@@ -2357,7 +2357,8 @@ make_message (char *name, char *value)
+     @{
+       /* @r{Reallocate buffer now that we know
+          how much space is needed.} */
+-      buffer = (char *) xrealloc (buffer, nchars + 1);
++      size = nchars + 1;
++      buffer = (char *) xrealloc (buffer, size);
+       if (buffer != NULL)
+         /* @r{Try again.} */
+@@ -4852,8 +4853,9 @@ Got r
+ @comment GNU
+ @deftypefun {FILE *} open_memstream (char **@var{ptr}, size_t *@var{sizeloc})
+ This function opens a stream for writing to a buffer.  The buffer is
+-allocated dynamically (as with @code{malloc}; @pxref{Unconstrained
+-Allocation}) and grown as necessary.
++allocated dynamically and grown as necessary, using @code{malloc}.
++After you've closed the stream, this buffer is your responsibility to
++clean up using @code{free} or @code{realloc}.  @xref{Unconstrained Allocation}.
+ When the stream is closed with @code{fclose} or flushed with
+ @code{fflush}, the locations @var{ptr} and @var{sizeloc} are updated to
diff --git a/src/patches/glibc/glibc-dst-req-static.patch b/src/patches/glibc/glibc-dst-req-static.patch
new file mode 100644 (file)
index 0000000..2161a0f
--- /dev/null
@@ -0,0 +1,58 @@
+2007-03-16  Jakub Jelinek  <jakub@redhat.com>
+
+       * elf/dl-open.c (dl_open_worker): Declare l in 2 different
+       smaller scopes.
+       * elf/dl-dst.h (DL_DST_REQ_STATIC): Add l as macro argument.
+       (DL_DST_REQUIRED): Adjust user.
+
+--- libc/elf/dl-dst.h  9 May 2006 21:44:31 -0000       1.13
++++ libc/elf/dl-dst.h  17 Mar 2007 17:08:00 -0000      1.14
+@@ -50,7 +51,7 @@
+                                                                             \
+          First get the origin string if it is not available yet.            \
+          This can only happen for the map of the executable.  */            \
+-      DL_DST_REQ_STATIC                                                     \
++      DL_DST_REQ_STATIC (l)                                                 \
+       if ((l)->l_origin == NULL)                                            \
+         {                                                                   \
+           assert ((l)->l_name[0] == '\0');                                  \
+@@ -68,9 +69,9 @@
+     __len; })
+ #ifdef SHARED
+-# define DL_DST_REQ_STATIC /* nothing */
++# define DL_DST_REQ_STATIC(l) /* nothing */
+ #else
+-# define DL_DST_REQ_STATIC \
++# define DL_DST_REQ_STATIC(l) \
+   if ((l) == NULL)                                                          \
+     {                                                                       \
+       const char *origin = _dl_get_origin ();                               \
+--- libc/elf/dl-open.c 29 Oct 2006 21:45:26 -0000      1.136
++++ libc/elf/dl-open.c 17 Mar 2007 17:07:51 -0000      1.137
+@@ -161,7 +161,7 @@ dl_open_worker (void *a)
+   struct dl_open_args *args = a;
+   const char *file = args->file;
+   int mode = args->mode;
+-  struct link_map *new, *l;
++  struct link_map *new;
+   int lazy;
+   unsigned int i;
+   bool any_tls = false;
+@@ -186,6 +186,7 @@ dl_open_worker (void *a)
+        By default we assume this is the main application.  */
+       call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
++      struct link_map *l;
+       for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
+       for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
+         if (caller_dlopen >= (const void *) l->l_map_start
+@@ -325,7 +326,7 @@ dl_open_worker (void *a)
+   /* Relocate the objects loaded.  We do this in reverse order so that copy
+      relocs of earlier objects overwrite the data written by later objects.  */
+-  l = new;
++  struct link_map *l = new;
+   while (l->l_next)
+     l = l->l_next;
+   while (1)
diff --git a/src/patches/glibc/glibc-dtv-is_static.patch b/src/patches/glibc/glibc-dtv-is_static.patch
new file mode 100644 (file)
index 0000000..d1b5c62
--- /dev/null
@@ -0,0 +1,642 @@
+2006-02-03  Roland McGrath  <roland@redhat.com>
+
+       * structs.def: Add a descriptor for pointer.val field of dtv_t.
+       * td_thr_tlsbase.c (td_thr_tlsbase): Extract pointer.val field from
+       DTV slot.
+
+2005-11-22  Jakub Jelinek  <jakub@redhat.com>
+
+       * elf/rtld.c (_dl_start): Fixup for dtv_t change.
+       * sysdeps/alpha/libc-tls.c (__tls_get_addr): Likewise.
+       * sysdeps/ia64/libc-tls.c (__tls_get_addr): Likewise.
+linuxthreads_db/
+       * td_thr_tlsbase.c (td_thr_tlsbase): Fixup for dtv_t change.
+linuxthreads/
+       * pthread.c (init_one_static_tls): Fixup for dtv_t change.
+       * sysdeps/alpha/tls.h (dtv_t): Change pointer type to be struct which
+       also contains information whether the memory pointed to is static
+       TLS or not.
+       * sysdeps/i386/tls.h: Likewise.
+       * sysdeps/ia64/tls.h: Likewise.
+       * sysdeps/powerpc/tls.h: Likewise.
+       * sysdeps/s390/tls.h: Likewise.
+       * sysdeps/sh/tls.h: Likewise.
+       * sysdeps/sparc/tls.h: Likewise.
+       * sysdeps/x86_64/tls.h: Likewise.
+
+2005-01-06  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/generic/dl-tls.c: Fixup for dtv_t change.
+       Fix updating of DTV.
+       * sysdeps/generic/libc-tls.c: Likewise.
+       * sysdeps/generic/dl-tls.c: Likewise.
+       * elf/dl-reloc.c (_dl_nothread_init_static_tls): Likewise.
+nptl/
+       * allocatestack.c (init_one_static_tls): Adjust initialization of DTV
+       entry for static tls deallocation fix.
+       * sysdeps/alpha/tls.h (dtv_t): Change pointer type to be struct which
+       also contains information whether the memory pointed to is static
+       TLS or not.
+       * sysdeps/i386/tls.h: Likewise.
+       * sysdeps/ia64/tls.h: Likewise.
+       * sysdeps/powerpc/tls.h: Likewise.
+       * sysdeps/s390/tls.h: Likewise.
+       * sysdeps/sh/tls.h: Likewise.
+       * sysdeps/sparc/tls.h: Likewise.
+       * sysdeps/x86_64/tls.h: Likewise.
+
+--- libc/elf/rtld.c.jj 2005-11-17 13:07:34.000000000 +0100
++++ libc/elf/rtld.c    2005-11-22 17:37:13.000000000 +0100
+@@ -448,18 +448,19 @@ _dl_start (void *arg)
+          counter.  */
+       initdtv[0].counter = 1;
+       initdtv[1].counter = 0;
++      initdtv[2].pointer.is_static = true;
+       /* Initialize the TLS block.  */
+ # if TLS_TCB_AT_TP
+-      initdtv[2].pointer = tlsblock;
++      initdtv[2].pointer.val = tlsblock;
+ # elif TLS_DTV_AT_TP
+       bootstrap_map.l_tls_offset = roundup (TLS_INIT_TCB_SIZE,
+                                             bootstrap_map.l_tls_align);
+-      initdtv[2].pointer = (char *) tlsblock + bootstrap_map.l_tls_offset;
++      initdtv[2].pointer.val = (char *) tlsblock + bootstrap_map.l_tls_offset;
+ # else
+ #  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+ # endif
+-      p = __mempcpy (initdtv[2].pointer, bootstrap_map.l_tls_initimage,
++      p = __mempcpy (initdtv[2].pointer.val, bootstrap_map.l_tls_initimage,
+                      bootstrap_map.l_tls_initimage_size);
+ # ifdef HAVE_BUILTIN_MEMSET
+       __builtin_memset (p, '\0', (bootstrap_map.l_tls_blocksize
+--- libc/elf/dl-reloc.c.jj     2005-02-26 02:09:47.000000000 +0100
++++ libc/elf/dl-reloc.c        2005-11-22 17:34:42.000000000 +0100
+@@ -116,7 +116,8 @@ _dl_nothread_init_static_tls (struct lin
+   /* Fill in the DTV slot so that a later LD/GD access will find it.  */
+   dtv_t *dtv = THREAD_DTV ();
+   assert (map->l_tls_modid <= dtv[-1].counter);
+-  dtv[map->l_tls_modid].pointer = dest;
++  dtv[map->l_tls_modid].pointer.val = dest;
++  dtv[map->l_tls_modid].pointer.is_static = true;
+   /* Initialize the memory.  */
+   memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
+--- libc/sysdeps/alpha/libc-tls.c.jj   2003-01-17 20:19:37.000000000 +0100
++++ libc/sysdeps/alpha/libc-tls.c      2005-11-22 17:37:59.000000000 +0100
+@@ -31,7 +31,7 @@ void *
+ __tls_get_addr (tls_index *ti)
+ {
+   dtv_t *dtv = THREAD_DTV ();
+-  return (char *) dtv[1].pointer + ti->ti_offset;
++  return (char *) dtv[1].pointer.val + ti->ti_offset;
+ }
+ #endif
+--- libc/sysdeps/ia64/libc-tls.c.jj    2003-01-12 09:54:39.000000000 +0100
++++ libc/sysdeps/ia64/libc-tls.c       2005-11-22 17:38:38.000000000 +0100
+@@ -30,7 +30,7 @@ void *
+ __tls_get_addr (size_t m, size_t offset)
+ {
+   dtv_t *dtv = THREAD_DTV ();
+-  return (char *) dtv[1].pointer + offset;
++  return (char *) dtv[1].pointer.val + offset;
+ }
+ #endif
+--- libc/sysdeps/generic/dl-tls.c.jj   2005-02-16 11:23:02.000000000 +0100
++++ libc/sysdeps/generic/dl-tls.c      2005-11-22 17:56:09.000000000 +0100
+@@ -418,7 +418,8 @@ _dl_allocate_tls_init (void *result)
+           {
+             /* For dynamically loaded modules we simply store
+                the value indicating deferred allocation.  */
+-            dtv[map->l_tls_modid].pointer = TLS_DTV_UNALLOCATED;
++            dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
++            dtv[map->l_tls_modid].pointer.is_static = false;
+             continue;
+           }
+@@ -434,7 +435,8 @@ _dl_allocate_tls_init (void *result)
+ # endif
+         /* Copy the initialization image and clear the BSS part.  */
+-        dtv[map->l_tls_modid].pointer = dest;
++        dtv[map->l_tls_modid].pointer.val = dest;
++        dtv[map->l_tls_modid].pointer.is_static = true;
+         memset (__mempcpy (dest, map->l_tls_initimage,
+                            map->l_tls_initimage_size), '\0',
+                 map->l_tls_blocksize - map->l_tls_initimage_size);
+@@ -603,10 +605,11 @@ __tls_get_addr (GET_ADDR_ARGS)
+                   {
+                     /* If this modid was used at some point the memory
+                        might still be allocated.  */
+-                    if (dtv[total + cnt].pointer != TLS_DTV_UNALLOCATED)
++                    if (! dtv[total + cnt].pointer.is_static
++                        && dtv[total + cnt].pointer.val != TLS_DTV_UNALLOCATED)
+                       {
+-                        free (dtv[total + cnt].pointer);
+-                        dtv[total + cnt].pointer = TLS_DTV_UNALLOCATED;
++                        free (dtv[total + cnt].pointer.val);
++                        dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
+                       }
+                     continue;
+@@ -662,16 +665,18 @@ __tls_get_addr (GET_ADDR_ARGS)
+                    dtv entry free it.  */
+                 /* XXX Ideally we will at some point create a memory
+                    pool.  */
+-                if (dtv[modid].pointer != TLS_DTV_UNALLOCATED)
++                if (! dtv[modid].pointer.is_static
++                    && dtv[modid].pointer.val != TLS_DTV_UNALLOCATED)
+                   /* Note that free is called for NULL is well.  We
+                      deallocate even if it is this dtv entry we are
+                      supposed to load.  The reason is that we call
+                      memalign and not malloc.  */
+-                  free (dtv[modid].pointer);
++                  free (dtv[modid].pointer.val);
+                 /* This module is loaded dynamically- We defer
+                    memory allocation.  */
+-                dtv[modid].pointer = TLS_DTV_UNALLOCATED;
++                dtv[modid].pointer.is_static = false;
++                dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
+                 if (modid == GET_ADDR_MODULE)
+                   the_map = map;
+@@ -686,7 +691,7 @@ __tls_get_addr (GET_ADDR_ARGS)
+       }
+     }
+-  p = dtv[GET_ADDR_MODULE].pointer;
++  p = dtv[GET_ADDR_MODULE].pointer.val;
+   if (__builtin_expect (p == TLS_DTV_UNALLOCATED, 0))
+     {
+@@ -706,7 +711,8 @@ __tls_get_addr (GET_ADDR_ARGS)
+         the_map = listp->slotinfo[idx].map;
+       }
+-      p = dtv[GET_ADDR_MODULE].pointer = allocate_and_init (the_map);
++      p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map);
++      dtv[GET_ADDR_MODULE].pointer.is_static = false;
+     }
+   return (char *) p + GET_ADDR_OFFSET;
+--- libc/sysdeps/generic/libc-tls.c.jj 2005-02-26 02:09:44.000000000 +0100
++++ libc/sysdeps/generic/libc-tls.c    2005-11-22 17:33:41.000000000 +0100
+@@ -177,17 +177,18 @@ __libc_setup_tls (size_t tcbsize, size_t
+   /* Initialize the TLS block.  */
+ # if TLS_TCB_AT_TP
+-  static_dtv[2].pointer = ((char *) tlsblock + tcb_offset
+-                         - roundup (memsz, align ?: 1));
++  static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset
++                             - roundup (memsz, align ?: 1));
+   static_map.l_tls_offset = roundup (memsz, align ?: 1);
+ # elif TLS_DTV_AT_TP
+-  static_dtv[2].pointer = (char *) tlsblock + tcb_offset;
++  static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset;
+   static_map.l_tls_offset = tcb_offset;
+ # else
+ #  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+ # endif
++  static_dtv[2].pointer.is_static = true;
+   /* sbrk gives us zero'd memory, so we don't need to clear the remainder.  */
+-  memcpy (static_dtv[2].pointer, initimage, filesz);
++  memcpy (static_dtv[2].pointer.val, initimage, filesz);
+   /* Install the pointer to the dtv.  */
+--- libc/linuxthreads_db/td_thr_tlsbase.c.jj   2004-03-14 04:40:06.000000000 +0100
++++ libc/linuxthreads_db/td_thr_tlsbase.c      2005-11-22 18:01:28.000000000 +0100
+@@ -59,10 +59,10 @@ td_thr_tlsbase (const td_thrhandle_t *th
+   /* It could be that the memory for this module is not allocated for
+      the given thread.  */
+-  if (pdtv.pointer == TLS_DTV_UNALLOCATED)
++  if (pdtv.pointer.val == TLS_DTV_UNALLOCATED)
+     return TD_TLSDEFER;
+-  *base = (char *) pdtv.pointer;
++  *base = (char *) pdtv.pointer.val;
+   return TD_OK;
+ #else
+--- libc/nptl/sysdeps/alpha/tls.h.jj   2004-01-16 06:23:05.000000000 +0100
++++ libc/nptl/sysdeps/alpha/tls.h      2005-11-22 17:33:41.000000000 +0100
+@@ -23,6 +23,7 @@
+ # include <dl-sysdep.h>
+ #ifndef __ASSEMBLER__
++# include <stdbool.h>
+ # include <stddef.h>
+ # include <stdint.h>
+@@ -30,7 +31,11 @@
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+ #else /* __ASSEMBLER__ */
+--- libc/nptl/sysdeps/s390/tls.h.jj    2004-03-08 19:41:36.000000000 +0100
++++ libc/nptl/sysdeps/s390/tls.h       2005-11-22 17:33:41.000000000 +0100
+@@ -22,6 +22,7 @@
+ #include <dl-sysdep.h>
+ #ifndef __ASSEMBLER__
++# include <stdbool.h>
+ # include <stddef.h>
+ # include <stdint.h>
+ # include <stdlib.h>
+@@ -32,7 +33,11 @@
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+--- libc/nptl/sysdeps/powerpc/tls.h.jj 2004-01-06 11:31:07.000000000 +0100
++++ libc/nptl/sysdeps/powerpc/tls.h    2005-11-22 17:33:41.000000000 +0100
+@@ -23,6 +23,7 @@
+ # include <dl-sysdep.h>
+ #ifndef __ASSEMBLER__
++# include <stdbool.h>
+ # include <stddef.h>
+ # include <stdint.h>
+@@ -30,7 +31,11 @@
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+ #else /* __ASSEMBLER__ */
+--- libc/nptl/sysdeps/sparc/tls.h.jj   2004-01-06 11:31:07.000000000 +0100
++++ libc/nptl/sysdeps/sparc/tls.h      2005-11-22 17:33:41.000000000 +0100
+@@ -22,6 +22,7 @@
+ #include <dl-sysdep.h>
+ #ifndef __ASSEMBLER__
++# include <stdbool.h>
+ # include <stddef.h>
+ # include <stdint.h>
+ # include <stdlib.h>
+@@ -31,7 +32,11 @@
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+ typedef struct
+--- libc/nptl/sysdeps/sh/tls.h.jj      2004-11-19 00:59:45.000000000 +0100
++++ libc/nptl/sysdeps/sh/tls.h 2005-11-22 17:33:41.000000000 +0100
+@@ -23,6 +23,7 @@
+ # include <dl-sysdep.h>
+ #ifndef __ASSEMBLER__
++# include <stdbool.h>
+ # include <stddef.h>
+ # include <stdint.h>
+@@ -30,7 +31,11 @@
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+ typedef struct
+--- libc/nptl/sysdeps/i386/tls.h.jj    2005-02-16 09:45:55.000000000 +0100
++++ libc/nptl/sysdeps/i386/tls.h       2005-11-22 17:33:41.000000000 +0100
+@@ -22,6 +22,7 @@
+ #include <dl-sysdep.h>
+ #ifndef __ASSEMBLER__
++# include <stdbool.h>
+ # include <stddef.h>
+ # include <stdint.h>
+ # include <stdlib.h>
+@@ -32,7 +33,11 @@
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+--- libc/nptl/sysdeps/ia64/tls.h.jj    2004-03-07 23:05:39.000000000 +0100
++++ libc/nptl/sysdeps/ia64/tls.h       2005-11-22 17:33:41.000000000 +0100
+@@ -22,6 +22,7 @@
+ #include <dl-sysdep.h>
+ #ifndef __ASSEMBLER__
++# include <stdbool.h>
+ # include <stddef.h>
+ # include <stdint.h>
+ # include <stdlib.h>
+@@ -32,7 +33,11 @@
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+--- libc/nptl/sysdeps/x86_64/tls.h.jj  2003-09-09 09:00:21.000000000 +0200
++++ libc/nptl/sysdeps/x86_64/tls.h     2005-11-22 17:33:41.000000000 +0100
+@@ -22,6 +22,7 @@
+ #include <asm/prctl.h>        /* For ARCH_SET_FS.  */
+ #ifndef __ASSEMBLER__
++# include <stdbool.h>
+ # include <stddef.h>
+ # include <stdint.h>
+ # include <stdlib.h>
+@@ -31,7 +32,11 @@
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+--- libc/nptl/allocatestack.c.jj       2005-11-17 13:07:35.000000000 +0100
++++ libc/nptl/allocatestack.c  2005-11-22 17:33:41.000000000 +0100
+@@ -925,7 +925,8 @@ init_one_static_tls (struct pthread *cur
+ # endif
+   /* Fill in the DTV slot so that a later LD/GD access will find it.  */
+-  dtv[map->l_tls_modid].pointer = dest;
++  dtv[map->l_tls_modid].pointer.val = dest;
++  dtv[map->l_tls_modid].pointer.is_static = true;
+   /* Initialize the memory.  */
+   memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
+--- libc/linuxthreads/sysdeps/alpha/tls.h.jj   2005-11-17 13:07:34.000000000 +0100
++++ libc/linuxthreads/sysdeps/alpha/tls.h      2005-11-22 17:43:32.000000000 +0100
+@@ -24,12 +24,17 @@
+ # include <pt-machine.h>
+ # include <stddef.h>
++# include <stdbool.h>
+ /* Type for the dtv.  */
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+--- libc/linuxthreads/sysdeps/s390/tls.h.jj    2005-11-17 13:07:34.000000000 +0100
++++ libc/linuxthreads/sysdeps/s390/tls.h       2005-11-22 17:42:01.000000000 +0100
+@@ -24,12 +24,17 @@
+ # include <pt-machine.h>
+ # include <stddef.h>
++# include <stdbool.h>
+ /* Type for the dtv.  */
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+ typedef struct
+--- libc/linuxthreads/sysdeps/powerpc/tls.h.jj 2005-11-17 13:07:34.000000000 +0100
++++ libc/linuxthreads/sysdeps/powerpc/tls.h    2005-11-22 17:41:08.000000000 +0100
+@@ -24,12 +24,17 @@
+ # include <pt-machine.h>
+ # include <stddef.h>
++# include <stdbool.h>
+ /* Type for the dtv.  */
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+ #else /* __ASSEMBLER__ */
+--- libc/linuxthreads/sysdeps/sparc/tls.h.jj   2005-11-17 13:07:34.000000000 +0100
++++ libc/linuxthreads/sysdeps/sparc/tls.h      2005-11-22 17:42:36.000000000 +0100
+@@ -24,12 +24,17 @@
+ # include <pt-machine.h>
+ # include <stddef.h>
++# include <stdbool.h>
+ /* Type for the dtv.  */
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+ typedef struct
+--- libc/linuxthreads/sysdeps/sh/tls.h.jj      2005-11-17 13:07:34.000000000 +0100
++++ libc/linuxthreads/sysdeps/sh/tls.h 2005-11-22 17:42:18.000000000 +0100
+@@ -26,12 +26,17 @@
+ #ifndef __ASSEMBLER__
+ # include <stddef.h>
+ # include <stdint.h>
++# include <stdbool.h>
+ /* Type for the dtv.  */
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+ #else /* __ASSEMBLER__ */
+--- libc/linuxthreads/sysdeps/i386/tls.h.jj    2005-11-17 13:07:34.000000000 +0100
++++ libc/linuxthreads/sysdeps/i386/tls.h       2005-11-22 17:41:26.000000000 +0100
+@@ -24,6 +24,7 @@
+ # include <pt-machine.h>
+ #ifndef __ASSEMBLER__
++# include <stdbool.h>
+ # include <stddef.h>
+ # include <stdint.h>
+@@ -31,7 +32,11 @@
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+--- libc/linuxthreads/sysdeps/ia64/tls.h.jj    2005-11-17 13:07:34.000000000 +0100
++++ libc/linuxthreads/sysdeps/ia64/tls.h       2005-11-22 17:41:32.000000000 +0100
+@@ -22,6 +22,7 @@
+ #ifndef __ASSEMBLER__
++# include <stdbool.h>
+ # include <dl-sysdep.h>
+ # include <pt-machine.h>
+ # include <stddef.h>
+@@ -30,7 +31,11 @@
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+ #else /* __ASSEMBLER__ */
+--- libc/linuxthreads/sysdeps/x86_64/tls.h.jj  2005-11-17 13:07:34.000000000 +0100
++++ libc/linuxthreads/sysdeps/x86_64/tls.h     2005-11-22 17:43:00.000000000 +0100
+@@ -24,12 +24,17 @@
+ # include <pt-machine.h>
+ # include <stddef.h>
++# include <stdbool.h>
+ /* Type for the dtv.  */
+ typedef union dtv
+ {
+   size_t counter;
+-  void *pointer;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
+ } dtv_t;
+--- libc/linuxthreads/pthread.c.jj     2004-10-06 10:04:43.000000000 +0200
++++ libc/linuxthreads/pthread.c        2005-11-22 18:02:06.000000000 +0100
+@@ -482,7 +482,8 @@ init_one_static_tls (pthread_descr descr
+ # endif
+   /* Fill in the DTV slot so that a later LD/GD access will find it.  */
+-  dtv[map->l_tls_modid].pointer = dest;
++  dtv[map->l_tls_modid].pointer.val = dest;
++  dtv[map->l_tls_modid].pointer.is_static = true;
+   /* Initialize the memory.  */
+   memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
+--- libc/nptl_db/structs.def   18 Dec 2003 02:51:04 -0000      1.2
++++ libc/nptl_db/structs.def   4 Feb 2006 00:47:58 -0000       1.3
+@@ -74,6 +74,8 @@ DB_STRUCT_FIELD (link_map, l_tls_modid)
+ #if !defined IS_IN_libpthread || USE_TLS
+ DB_STRUCT_ARRAY_FIELD (dtv, dtv)
++# define pointer_val pointer.val /* Field of anonymous struct in dtv_t.  */
++DB_STRUCT_FIELD (dtv_t, pointer_val)
+ #endif
+ #if !defined IS_IN_libpthread || TLS_TCB_AT_TP
+ DB_STRUCT_FIELD (pthread, dtvp)
+--- libc/nptl_db/td_thr_tlsbase.c      9 Sep 2003 06:57:51 -0000       1.2
++++ libc/nptl_db/td_thr_tlsbase.c      4 Feb 2006 00:47:58 -0000       1.3
+@@ -25,7 +25,7 @@ td_thr_tlsbase (const td_thrhandle_t *th
+               psaddr_t *base)
+ {
+   td_err_e err;
+-  psaddr_t dtv, dtvptr;
++  psaddr_t dtv, dtvslot, dtvptr;
+   if (modid < 1)
+     return TD_NOTLS;
+@@ -35,8 +35,13 @@ td_thr_tlsbase (const td_thrhandle_t *th
+   if (err != TD_OK)
+     return err;
+-  /* Get the corresponding entry in the DTV.  */
+-  err = DB_GET_FIELD (dtvptr, th->th_ta_p, dtv, dtv, dtv, modid);
++  /* Find the corresponding entry in the DTV.  */
++  err = DB_GET_FIELD_ADDRESS (dtvslot, th->th_ta_p, dtv, dtv, dtv, modid);
++  if (err != TD_OK)
++    return err;
++
++  /* Extract the TLS block address from that DTV slot.  */
++  err = DB_GET_FIELD (dtvptr, th->th_ta_p, dtvslot, dtv_t, pointer_val, 0);
+   if (err != TD_OK)
+     return err;
diff --git a/src/patches/glibc/glibc-elf64-filebuf-size.patch b/src/patches/glibc/glibc-elf64-filebuf-size.patch
new file mode 100644 (file)
index 0000000..f2c0bde
--- /dev/null
@@ -0,0 +1,35 @@
+2005-07-30  Ulrich Drepper  <drepper@redhat.com>
+
+       * elf/dl-load.c [__WORDSIZE==64] (FILEBUF_SIZE): Adjust the value
+       up.  We have more program header entries now and the note section
+       was normally not loaded.
+
+--- libc/elf/dl-load.c 26 Apr 2005 04:25:58 -0000      1.268
++++ libc/elf/dl-load.c 30 Jul 2005 21:14:33 -0000      1.269
+@@ -122,19 +122,19 @@ int __stack_prot attribute_hidden attrib
+    question is how large are the ELF and program header combined.  The
+    ELF header 32-bit files is 52 bytes long and in 64-bit files is 64
+    bytes long.  Each program header entry is again 32 and 56 bytes
+-   long respectively.  I.e., even with a file which has 7 program
+-   header entries we only have to read 512B.  Add to this a bit of
+-   margin for program notes and reading 512B and 640B for 32-bit and
+-   64-bit files respecitvely is enough.  If this heuristic should
+-   really fail for some file the code in `_dl_map_object_from_fd'
+-   knows how to recover.  */
++   long respectively.  I.e., even with a file which has 10 program
++   header entries we only have to read 372B/624B respectively.  Add to
++   this a bit of margin for program notes and reading 512B and 832B
++   for 32-bit and 64-bit files respecitvely is enough.  If this
++   heuristic should really fail for some file the code in
++   `_dl_map_object_from_fd' knows how to recover.  */
+ struct filebuf
+ {
+   ssize_t len;
+ #if __WORDSIZE == 32
+ # define FILEBUF_SIZE 512
+ #else
+-# define FILEBUF_SIZE 640
++# define FILEBUF_SIZE 832
+ #endif
+   char buf[FILEBUF_SIZE] __attribute__ ((aligned (__alignof (ElfW(Ehdr)))));
+ };
diff --git a/src/patches/glibc/glibc-euidaccess.patch b/src/patches/glibc/glibc-euidaccess.patch
new file mode 100644 (file)
index 0000000..b6dd2e2
--- /dev/null
@@ -0,0 +1,70 @@
+2005-11-27  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/posix/euidaccess.c [_LIBC] (euidaccess): Don't cache
+       euid and egid.
+
+--- libc/sysdeps/posix/euidaccess.c    6 Jul 2001 04:56:01 -0000       1.11
++++ libc/sysdeps/posix/euidaccess.c    27 Nov 2005 17:13:35 -0000      1.12
+@@ -93,14 +93,6 @@ static uid_t uid;
+ /* The user's real group id. */
+ static gid_t gid;
+-#ifdef HAVE_GETGROUPS
+-int group_member ();
+-#else
+-#define group_member(gid)     0
+-#endif
+-
+-#endif
+-
+ /* The user's effective user id. */
+ static uid_t euid;
+@@ -110,6 +102,14 @@ static gid_t egid;
+ /* Nonzero if UID, GID, EUID, and EGID have valid values. */
+ static int have_ids;
++# ifdef HAVE_GETGROUPS
++int group_member ();
++# else
++#  define group_member(gid)   0
++# endif
++
++#endif
++
+ /* Return 0 if the user has permission of type MODE on file PATH;
+    otherwise, return -1 and set `errno' to EACCESS.
+@@ -126,6 +126,9 @@ euidaccess (path, mode)
+   int granted;
+ #ifdef        _LIBC
++  uid_t euid;
++  gid_t egid;
++
+   if (! __libc_enable_secure)
+     /* If we are not set-uid or set-gid, access does the same.  */
+     return __access (path, mode);
+@@ -157,12 +160,8 @@ euidaccess (path, mode)
+ #ifdef        _LIBC
+   /* Now we need the IDs.  */
+-  if (have_ids == 0)
+-    {
+-      have_ids = 1;
+-      euid = __geteuid ();
+-      egid = __getegid ();
+-    }
++  euid = __geteuid ();
++  egid = __getegid ();
+ #endif
+   /* The super-user can read and write any file, and execute any file
+@@ -177,6 +176,7 @@ euidaccess (path, mode)
+     granted = (unsigned) (stats.st_mode & (mode << 3)) >> 3;
+   else
+     granted = (stats.st_mode & mode);
++  /* XXX Add support for ACLs.  */
+   if (granted == mode)
+     return 0;
+   __set_errno (EACCESS);
diff --git a/src/patches/glibc/glibc-fgets-1.patch b/src/patches/glibc/glibc-fgets-1.patch
new file mode 100644 (file)
index 0000000..f4b87f0
--- /dev/null
@@ -0,0 +1,112 @@
+2005-09-26  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #713]
+       * libio/iofgets.c: Treat N==1 correctly.
+       * libio/iofgets_u.c: Likewise.
+       * libio/iofgetws.c: Likewise.
+       * libio/iofgetws_u.c: Likewise.
+       * stdio-common/Makefile (tests): Add tst-fgets.
+       * stdio-common/tst-fgets.c: New file.
+
+--- libc/stdio-common/tst-fgets.c 1 Jan 1970 00:00:00 -0000
++++ libc/stdio-common/tst-fgets.c      26 Sep 2005 23:59:46 -0000      1.1
+@@ -0,0 +1,20 @@
++/* Derived from the test case in
++   http://sourceware.org/bugzilla/show_bug.cgi?id=713.  */
++#include <stdio.h>
++
++static int
++do_test (void)
++{
++  FILE *fp = fmemopen ("hello", 5, "r");
++  char buf[2];
++  char *bp = fgets (buf, sizeof (buf), fp);
++  printf ("fgets: %s\n", bp == buf ? "OK" : "ERROR");
++  int res = bp != buf;
++  bp = fgets_unlocked (buf, sizeof (buf), fp);
++  printf ("fgets_unlocked: %s\n", bp == buf ? "OK" : "ERROR");
++  res |= bp != buf;
++  return res;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/stdio-common/Makefile 4 Sep 2005 20:04:54 -0000       1.93
++++ libc/stdio-common/Makefile 26 Sep 2005 23:58:58 -0000      1.94
+@@ -53,7 +53,7 @@ tests := tstscanf test_rdwr test-popen t
+        scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf \
+        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-popen tst-unlockedio tst-fmemopen2 tst-fgets
+ test-srcs = tst-unbputc tst-printf
+--- libc/libio/iofgets.c       29 Aug 2003 19:58:27 -0000      1.17
++++ libc/libio/iofgets.c       26 Sep 2005 23:55:00 -0000      1.18
+@@ -41,6 +41,14 @@ _IO_fgets (buf, n, fp)
+   CHECK_FILE (fp, NULL);
+   if (n <= 0)
+     return NULL;
++  if (__builtin_expect (n == 1, 0))
++    {
++      /* Another irregular case: since we have to store a NUL byte and
++       there is only room for exactly one byte, we don't have to
++       read anything.  */
++      buf[0] = '\0';
++      return buf;
++    }
+   _IO_acquire_lock (fp);
+   /* This is very tricky since a file descriptor may be in the
+      non-blocking mode. The error flag doesn't mean much in this
+--- libc/libio/iofgets_u.c     4 Aug 2002 20:32:04 -0000       1.5
++++ libc/libio/iofgets_u.c     26 Sep 2005 23:54:27 -0000      1.6
+@@ -40,6 +40,14 @@ fgets_unlocked (buf, n, fp)
+   CHECK_FILE (fp, NULL);
+   if (n <= 0)
+     return NULL;
++  if (__builtin_expect (n == 1, 0))
++    {
++      /* Another irregular case: since we have to store a NUL byte and
++       there is only room for exactly one byte, we don't have to
++       read anything.  */
++      buf[0] = '\0';
++      return buf;
++    }
+   /* This is very tricky since a file descriptor may be in the
+      non-blocking mode. The error flag doesn't mean much in this
+      case. We return an error only when there is a new error. */
+--- libc/libio/iofgetws.c      29 Aug 2003 19:58:27 -0000      1.4
++++ libc/libio/iofgetws.c      26 Sep 2005 23:53:54 -0000      1.5
+@@ -41,6 +41,14 @@ fgetws (buf, n, fp)
+   CHECK_FILE (fp, NULL);
+   if (n <= 0)
+     return NULL;
++  if (__builtin_expect (n == 1, 0))
++    {
++      /* Another irregular case: since we have to store a NUL byte and
++       there is only room for exactly one byte, we don't have to
++       read anything.  */
++      buf[0] = L'\0';
++      return buf;
++    }
+   _IO_acquire_lock (fp);
+   /* This is very tricky since a file descriptor may be in the
+      non-blocking mode. The error flag doesn't mean much in this
+--- libc/libio/iofgetws_u.c    6 Jul 2001 04:54:55 -0000       1.2
++++ libc/libio/iofgetws_u.c    26 Sep 2005 23:53:20 -0000      1.3
+@@ -40,6 +40,14 @@ fgetws_unlocked (buf, n, fp)
+   CHECK_FILE (fp, NULL);
+   if (n <= 0)
+     return NULL;
++  if (__builtin_expect (n == 1, 0))
++    {
++      /* Another irregular case: since we have to store a NUL byte and
++       there is only room for exactly one byte, we don't have to
++       read anything.  */
++      buf[0] = L'\0';
++      return buf;
++    }
+   /* This is very tricky since a file descriptor may be in the
+      non-blocking mode. The error flag doesn't mean much in this
+      case. We return an error only when there is a new error. */
diff --git a/src/patches/glibc/glibc-gai-leak.patch b/src/patches/glibc/glibc-gai-leak.patch
new file mode 100644 (file)
index 0000000..5b28835
--- /dev/null
@@ -0,0 +1,36 @@
+2006-03-29  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/posix/getaddrinfo.c (gaih_inet): No need to duplicate
+       'name' for 'canon'.  The final allocation will happen later.
+
+--- libc/sysdeps/posix/getaddrinfo.c   20 Dec 2005 16:49:19 -0000      1.93
++++ libc/sysdeps/posix/getaddrinfo.c   29 Mar 2006 17:49:24 -0000      1.94
+@@ -538,16 +538,10 @@ gaih_inet (const char *name, const struc
+         else
+           return -EAI_ADDRFAMILY;
+-      dupname:
+         if (req->ai_flags & AI_CANONNAME)
+-          {
+-            canon = strdup (name);
+-            if (canon == NULL)
+-              return -EAI_MEMORY;
+-          }
++          canon = name;
+       }
+-
+-      if (at->family == AF_UNSPEC)
++      else if (at->family == AF_UNSPEC)
+       {
+         char *namebuf = (char *) name;
+         char *scope_delim = strchr (name, SCOPE_DELIMITER);
+@@ -595,7 +589,8 @@ gaih_inet (const char *name, const struc
+                   }
+               }
+-            goto dupname;
++            if (req->ai_flags & AI_CANONNAME)
++              canon = name;
+           }
+       }
diff --git a/src/patches/glibc/glibc-gconv-cache-memleak.patch b/src/patches/glibc/glibc-gconv-cache-memleak.patch
new file mode 100644 (file)
index 0000000..0429645
--- /dev/null
@@ -0,0 +1,16 @@
+2006-01-10  Ulrich Drepper  <drepper@redhat.com>
+
+       * iconv/gconv_cache.c (free_mem): Don't call munmap if gconv_cache
+       is NULL.
+
+--- libc/iconv/gconv_cache.c   20 Dec 2005 16:20:35 -0000      1.20
++++ libc/iconv/gconv_cache.c   11 Jan 2006 07:08:29 -0000      1.21
+@@ -467,7 +467,7 @@ libc_freeres_fn (free_mem)
+   if (cache_malloced)
+     free (gconv_cache);
+ #ifdef _POSIX_MAPPED_FILES
+-  else
++  else if (gconv_cache != NULL)
+     __munmap (gconv_cache, cache_size);
+ #endif
+ }
diff --git a/src/patches/glibc/glibc-getconf-a.patch b/src/patches/glibc/glibc-getconf-a.patch
new file mode 100644 (file)
index 0000000..9f083ac
--- /dev/null
@@ -0,0 +1,81 @@
+2005-01-11  Thorsten Kukuk  <kukuk@suse.de>
+
+       [BZ #652]
+       * posix/getconf.c: Add new option -a to print the names of
+       the current system configuration variables to stdout.
+       Based on patch from Josh Aas <josha@sgi.com>.
+
+--- libc/posix/getconf.c       12 Jan 2005 23:39:50 -0000      1.39
++++ libc/posix/getconf.c       26 Sep 2005 23:00:46 -0000      1.40
+@@ -941,9 +941,54 @@ usage (void)
+   fprintf (stderr,
+          _("Usage: %s [-v specification] variable_name [pathname]\n"),
+          __progname);
++  fprintf (stderr,
++         _("       %s -a [pathname]\n"), __progname);
+   exit (2);
+ }
++static void
++print_all (const char *path)
++{
++  register const struct conf *c;
++  size_t clen;
++  long int value;
++  char *cvalue;
++  for (c = vars; c->name != NULL; ++c) {
++    printf("%-35s", c->name);
++    switch (c->call) {
++      case PATHCONF:
++        value = pathconf (path, c->call_name);
++        if (value != -1) {
++          printf("%ld", value);
++        }
++        printf("\n");
++        break;
++      case SYSCONF:
++        value = sysconf (c->call_name);
++        if (value == -1l) {
++          if (c->call_name == _SC_UINT_MAX
++            || c->call_name == _SC_ULONG_MAX)
++            printf ("%lu", value);
++        }
++        else {
++          printf ("%ld", value);
++        }
++        printf ("\n");
++        break;
++      case CONFSTR:
++        clen = confstr (c->call_name, (char *) NULL, 0);
++        cvalue = (char *) malloc (clen);
++        if (cvalue == NULL)
++          error (3, 0, _("memory exhausted"));
++        if (confstr (c->call_name, cvalue, clen) != clen)
++          error (3, errno, "confstr");
++        printf ("%.*s\n", (int) clen, cvalue);
++        break;
++    }
++  }
++  exit (0);
++}
++
+ int
+ main (int argc, char *argv[])
+ {
+@@ -1050,6 +1095,16 @@ warranty; not even for MERCHANTABILITY o
+       }
+     }
++  if (argc > 1 && strcmp (argv[1], "-a") == 0)
++    {
++      if (argc == 2)
++      print_all ("/");
++      else if (argc == 3)
++      print_all (argv[2]);
++      else
++      usage ();
++    }
++
+   if (argc < 2 || argc > 3)
+     usage ();
diff --git a/src/patches/glibc/glibc-getdelim-trunc.patch b/src/patches/glibc/glibc-getdelim-trunc.patch
new file mode 100644 (file)
index 0000000..ce5c1f1
--- /dev/null
@@ -0,0 +1,30 @@
+2005-10-13  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1405]
+       * libio/iogetdelim.c (_IO_getdelim): Fix truncation of return
+       value.  Avoid overflow in computation.
+
+--- libc/libio/iogetdelim.c    29 Aug 2003 19:58:27 -0000      1.13
++++ libc/libio/iogetdelim.c    14 Oct 2005 06:24:58 -0000      1.14
+@@ -45,7 +45,7 @@ _IO_getdelim (lineptr, n, delimiter, fp)
+      int delimiter;
+      _IO_FILE *fp;
+ {
+-  int result;
++  _IO_ssize_t result;
+   _IO_ssize_t cur_len = 0;
+   _IO_ssize_t len;
+@@ -91,6 +91,12 @@ _IO_getdelim (lineptr, n, delimiter, fp)
+       t = (char *) memchr ((void *) fp->_IO_read_ptr, delimiter, len);
+       if (t != NULL)
+       len = (t - fp->_IO_read_ptr) + 1;
++      if (__builtin_expect (cur_len + len + 1 < 0, 0))
++      {
++        __set_errno (EOVERFLOW);
++        result = -1;
++        goto unlock_return;
++      }
+       /* Make enough space for len+1 (for final NUL) bytes.  */
+       needed = cur_len + len + 1;
+       if (needed > *n)
diff --git a/src/patches/glibc/glibc-getent-gethostbyaddr.patch b/src/patches/glibc/glibc-getent-gethostbyaddr.patch
new file mode 100644 (file)
index 0000000..26cbf36
--- /dev/null
@@ -0,0 +1,19 @@
+2005-10-08  Jakub Jelinek  <jakub@redhat.com>
+
+       * nss/getent.c (hosts_keys): Pass INADDRSZ as size rather
+       than IN6ADDRSZ to AF_INET gethostbyaddr.
+
+--- libc/nss/getent.c  10 Sep 2005 02:37:44 -0000      1.26
++++ libc/nss/getent.c  8 Oct 2005 17:28:41 -0000       1.27
+@@ -280,9 +280,9 @@ hosts_keys (int number, char *key[])
+       char addr[IN6ADDRSZ];
+       if (inet_pton (AF_INET6, key[i], &addr) > 0)
+-      host = gethostbyaddr (addr, sizeof (addr), AF_INET6);
++      host = gethostbyaddr (addr, IN6ADDRSZ, AF_INET6);
+       else if (inet_pton (AF_INET, key[i], &addr) > 0)
+-      host = gethostbyaddr (addr, sizeof (addr), AF_INET);
++      host = gethostbyaddr (addr, INADDRSZ, AF_INET);
+       else if ((host = gethostbyname2 (key[i], AF_INET6)) == NULL)
+       host = gethostbyname2 (key[i], AF_INET);
diff --git a/src/patches/glibc/glibc-getent-leak.patch b/src/patches/glibc/glibc-getent-leak.patch
new file mode 100644 (file)
index 0000000..b03db4c
--- /dev/null
@@ -0,0 +1,15 @@
+2005-09-09  Ulrich Drepper  <drepper@redhat.com>
+
+       * nss/getent.c (netgroup_keys): Call endnetgrent.
+
+--- libc/nss/getent.c  16 Aug 2005 15:57:39 -0000      1.25
++++ libc/nss/getent.c  10 Sep 2005 02:37:44 -0000      1.26
+@@ -410,6 +411,8 @@ netgroup_keys (int number, char *key[])
+       }
+     }
++  endnetgrent ();
++
+   return result;
+ }
diff --git a/src/patches/glibc/glibc-glob-getlogin_r.patch b/src/patches/glibc/glibc-glob-getlogin_r.patch
new file mode 100644 (file)
index 0000000..634eb77
--- /dev/null
@@ -0,0 +1,17 @@
+2005-07-11  Derek R. Price  <derek@ximbiot.com>
+
+       [BZ #1061]
+       * sysdeps/generic/glob.c (glob): Only a 0 return from
+       getlogin_r means success, according to POSIX 1003.2.
+
+--- libc/sysdeps/generic/glob.c        27 Oct 2004 18:21:02 -0000      1.53
++++ libc/sysdeps/generic/glob.c        8 Sep 2005 08:09:03 -0000       1.54
+@@ -715,7 +715,7 @@ glob (pattern, flags, errfunc, pglob)
+               buflen = 20;
+             name = (char *) __alloca (buflen);
+-            success = getlogin_r (name, buflen) >= 0;
++            success = getlogin_r (name, buflen) == 0;
+ #   else
+             success = (name = getlogin ()) != NULL;
+ #   endif
diff --git a/src/patches/glibc/glibc-hwcap-mask.patch b/src/patches/glibc/glibc-hwcap-mask.patch
new file mode 100644 (file)
index 0000000..b04897b
--- /dev/null
@@ -0,0 +1,89 @@
+2007-07-01  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/generic/dl-sysdep.c (_dl_important_hwcaps): Add integer
+       overflow check.
+       * elf/dl-minimal.c (__libc_memalign): Likewise.  Handle malloc (0).
+       Return NULL if mmap failed instead of asserting it does not.
+       (calloc): Check for integer overflow.
+
+       * elf/dl-minimal.c (__strtoul_internal): Fix parsing of numbers bigger
+       than LONG_MAX / 10.
+
+--- libc/elf/dl-minimal.c      25 Jan 2007 17:10:40 -0000      1.53
++++ libc/elf/dl-minimal.c      4 Jul 2007 18:06:29 -0000       1.54
+@@ -75,14 +75,21 @@ __libc_memalign (size_t align, size_t n)
+   alloc_ptr = (void *) 0 + (((alloc_ptr - (void *) 0) + align - 1)
+                           & ~(align - 1));
+-  if (alloc_ptr + n >= alloc_end)
++  if (alloc_ptr + n >= alloc_end || n >= -(uintptr_t) alloc_ptr)
+     {
+       /* Insufficient space left; allocate another page.  */
+       caddr_t page;
+       size_t nup = (n + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1);
++      if (__builtin_expect (nup == 0, 0))
++      {
++        if (n)
++          return NULL;
++        nup = GLRO(dl_pagesize);
++      }
+       page = __mmap (0, nup, PROT_READ|PROT_WRITE,
+                    MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0);
+-      assert (page != MAP_FAILED);
++      if (page == MAP_FAILED)
++      return NULL;
+       if (page != alloc_end)
+       alloc_ptr = page;
+       alloc_end = page + nup;
+@@ -108,7 +115,14 @@ calloc (size_t nmemb, size_t size)
+   /* New memory from the trivial malloc above is always already cleared.
+      (We make sure that's true in the rare occasion it might not be,
+      by clearing memory in free, below.)  */
+-  return malloc (nmemb * size);
++  size_t bytes = nmemb * size;
++
++#define HALF_SIZE_T (((size_t) 1) << (8 * sizeof (size_t) / 2))
++  if (__builtin_expect ((nmemb | size) >= HALF_SIZE_T, 0)
++      && size != 0 && bytes / size != nmemb)
++    return NULL;
++
++  return malloc (bytes);
+ }
+ /* This will rarely be called.  */
+@@ -264,7 +278,7 @@ __strtoul_internal (const char *nptr, ch
+   while (*nptr >= '0' && *nptr <= '9')
+     {
+       unsigned long int digval = *nptr - '0';
+-      if (result > LONG_MAX / 10
++      if (result > ULONG_MAX / 10
+         || (result == ULONG_MAX / 10 && digval > ULONG_MAX % 10))
+       {
+         errno = ERANGE;
+--- libc/sysdeps/generic/dl-sysdep.c   27 Oct 2006 23:11:42 -0000      1.2
++++ libc/sysdeps/generic/dl-sysdep.c   4 Jul 2007 18:06:06 -0000       1.3
+@@ -460,9 +460,21 @@ _dl_important_hwcaps (const char *platfo
+     total = temp[0].len + 1;
+   else
+     {
+-      total = (1UL << (cnt - 2)) * (temp[0].len + temp[cnt - 1].len + 2);
+-      for (n = 1; n + 1 < cnt; ++n)
+-      total += (1UL << (cnt - 3)) * (temp[n].len + 1);
++      total = temp[0].len + temp[cnt - 1].len + 2;
++      if (cnt > 2)
++      {
++        total <<= 1;
++        for (n = 1; n + 1 < cnt; ++n)
++          total += temp[n].len + 1;
++        if (cnt > 3
++            && (cnt >= sizeof (size_t) * 8
++                || total + (sizeof (*result) << 3)
++                   >= (1UL << (sizeof (size_t) * 8 - cnt + 3))))
++          _dl_signal_error (ENOMEM, NULL, NULL,
++                            N_("cannot create capability list"));
++
++        total <<= cnt - 3;
++      }
+     }
+   /* The result structure: we use a very compressed way to store the
diff --git a/src/patches/glibc/glibc-hypotf.patch b/src/patches/glibc/glibc-hypotf.patch
new file mode 100644 (file)
index 0000000..e66bfd3
--- /dev/null
@@ -0,0 +1,51 @@
+2005-08-31  Bob Wilson  <bob.wilson@acm.org>
+
+       * sysdeps/ieee754/flt-32/e_hypotf.c (__ieee754_hypotf):  Remove the
+       exponent bias from the increment value for scaling by 2^60.
+
+2005-08-30  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/ieee754/flt-32/e_hypotf.c [!__STDC__]: Fix function name.
+
+2005-08-01  Bob Wilson  <bob.wilson@acm.org>
+        Richard Sandiford  <richard@codesourcery.com>
+
+       * sysdeps/ieee754/flt-32/e_hypotf.c (__ieee754_hypotf): Add missing
+       exponent bias to the value for 2^126.
+
+--- libc/sysdeps/ieee754/flt-32/e_hypotf.c     13 Jul 1999 23:58:13 -0000      1.1
++++ libc/sysdeps/ieee754/flt-32/e_hypotf.c     6 Sep 2005 05:36:56 -0000       1.3
+@@ -23,7 +23,7 @@ static char rcsid[] = "$NetBSD: e_hypotf
+ #ifdef __STDC__
+       float __ieee754_hypotf(float x, float y)
+ #else
+-      float __ieee754_hypot(x,y)
++      float __ieee754_hypotf(x,y)
+       float x, y;
+ #endif
+ {
+@@ -47,20 +47,20 @@ static char rcsid[] = "$NetBSD: e_hypotf
+              return w;
+          }
+          /* scale a and b by 2**-60 */
+-         ha -= 0x5d800000; hb -= 0x5d800000;  k += 60;
++         ha -= 0x1e000000; hb -= 0x1e000000;  k += 60;
+          SET_FLOAT_WORD(a,ha);
+          SET_FLOAT_WORD(b,hb);
+       }
+       if(hb < 0x26800000) {   /* b < 2**-50 */
+           if(hb <= 0x007fffff) {      /* subnormal b or 0 */
+               if(hb==0) return a;
+-              SET_FLOAT_WORD(t1,0x3f000000);  /* t1=2^126 */
++              SET_FLOAT_WORD(t1,0x7e800000);  /* t1=2^126 */
+               b *= t1;
+               a *= t1;
+               k -= 126;
+           } else {            /* scale a and b by 2^60 */
+-              ha += 0x5d800000;       /* a *= 2^60 */
+-              hb += 0x5d800000;       /* b *= 2^60 */
++              ha += 0x1e000000;       /* a *= 2^60 */
++              hb += 0x1e000000;       /* b *= 2^60 */
+               k -= 60;
+               SET_FLOAT_WORD(a,ha);
+               SET_FLOAT_WORD(b,hb);
diff --git a/src/patches/glibc/glibc-i386-futex-timed-wait.patch b/src/patches/glibc/glibc-i386-futex-timed-wait.patch
new file mode 100644 (file)
index 0000000..8ece3d2
--- /dev/null
@@ -0,0 +1,92 @@
+2006-02-08  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_futex_timedwait):
+       Add "memory" clobber.
+
+2006-01-05  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_futex_wait):
+       Return status.
+       (lll_futex_timed_wait): Define.
+       * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise.
+
+--- libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h.jj   2004-03-24 07:35:18.000000000 +0100
++++ libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h      2006-02-22 19:02:58.000000000 +0100
+@@ -66,18 +66,35 @@
+ #define lll_futex_wait(futex, val) \
+-  do {                                                                              \
+-    int __ignore;                                                           \
++  ({                                                                        \
++    int __status;                                                           \
+     register __typeof (val) _val asm ("edx") = (val);                       \
+     __asm __volatile (LLL_EBX_LOAD                                          \
+                     LLL_ENTER_KERNEL                                        \
+                     LLL_EBX_LOAD                                            \
+-                    : "=a" (__ignore)                                       \
++                    : "=a" (__status)                                       \
+                     : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (0),        \
+                       "c" (FUTEX_WAIT), "d" (_val),                         \
+                       "i" (offsetof (tcbhead_t, sysinfo))                   \
+                     : "memory");                                            \
+-  } while (0)
++    __status;                                                               \
++  })
++
++
++#define lll_futex_timed_wait(futex, val, timeout)                           \
++  ({                                                                        \
++    int __status;                                                           \
++    register __typeof (val) _val asm ("edx") = (val);                       \
++    __asm __volatile (LLL_EBX_LOAD                                          \
++                    LLL_ENTER_KERNEL                                        \
++                    LLL_EBX_LOAD                                            \
++                    : "=a" (__status)                                       \
++                    : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (timeout),  \
++                      "c" (FUTEX_WAIT), "d" (_val),                         \
++                      "i" (offsetof (tcbhead_t, sysinfo))                   \
++                    : "memory");                                            \
++    __status;                                                               \
++  })
+ #define lll_futex_wake(futex, nr) \
+--- libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h.jj 2004-07-05 19:29:20.000000000 +0200
++++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h    2006-02-22 19:02:58.000000000 +0100
+@@ -47,16 +47,31 @@
+ #define lll_futex_wait(futex, val) \
+-  do {                                                                              \
+-    int __ignore;                                                           \
++  ({                                                                        \
++    int __status;                                                           \
+     register __typeof (val) _val asm ("edx") = (val);                       \
+     __asm __volatile ("xorq %%r10, %%r10\n\t"                               \
+                     "syscall"                                               \
+-                    : "=a" (__ignore)                                       \
++                    : "=a" (__status)                                       \
+                     : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAIT),       \
+                       "d" (_val)                                            \
+                     : "memory", "cc", "r10", "r11", "cx");                  \
+-  } while (0)
++    __status;                                                               \
++  })
++
++
++#define lll_futex_timed_wait(futex, val, timeout)                           \
++  ({                                                                        \
++    register const struct timespec *__to __asm__ ("r10") = timeout;         \
++    int __status;                                                           \
++    register __typeof (val) _val asm ("edx") = (val);                       \
++    __asm __volatile ("syscall"                                                     \
++                    : "=a" (__status)                                       \
++                    : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAIT),       \
++                      "d" (_val), "r" (__to)                                \
++                    : "memory", "cc", "r11", "cx");                         \
++    __status;                                                               \
++  })
+ #define lll_futex_wake(futex, nr) \
diff --git a/src/patches/glibc/glibc-i386-nosegneg.patch b/src/patches/glibc/glibc-i386-nosegneg.patch
new file mode 100644 (file)
index 0000000..d4157e7
--- /dev/null
@@ -0,0 +1,255 @@
+--- libc/sysdeps/unix/sysv/linux/i386/dl-procinfo.c    2006-10-12 12:20:15.000000000 -0400
++++ libc/sysdeps/unix/sysv/linux/i386/dl-procinfo.c    2006-10-14 18:20:17.000000000 -0400
+@@ -0,0 +1,9 @@
++#ifndef PROCINFO_CLASS
++# define PROCINFO_CLASS
++#endif
++
++#if defined (PROCINFO_DECL) || !defined (SHARED)
++PROCINFO_CLASS int _dl_nosegneg;
++#endif
++
++#include <sysdeps/i386/dl-procinfo.c>
+--- libc/sysdeps/unix/sysv/linux/i386/dl-procinfo.h    2006-10-13 09:17:08.000000000 -0400
++++ libc/sysdeps/unix/sysv/linux/i386/dl-procinfo.h    2006-10-14 16:10:51.000000000 -0400
+@@ -43,0 +44,19 @@
++
++#define DL_ARCH_IMPORTANT_HWCAP(PAIR) \
++({                                            \
++  int _cnt = 0;                                       \
++  if (GLRO (dl_nosegneg))                     \
++    {                                         \
++      struct r_strlenpair *_pair = (PAIR);    \
++      if (_pair)                              \
++      {                                       \
++        _pair->str = "nosegneg";              \
++        _pair->len = 8;                       \
++      }                                       \
++      ++_cnt;                                 \
++    }                                         \
++  _cnt; })
++
++#define DL_ARCH_HWCAP_MASK \
++  (GLRO (dl_nosegneg)                                                 \
++   ? (1ULL << (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT)) : 0LL)
+--- libc/sysdeps/unix/sysv/linux/i386/dl-osinfo.h      2006-10-12 12:31:57.000000000 -0400
++++ libc/sysdeps/unix/sysv/linux/i386/dl-osinfo.h      2006-10-14 16:02:03.000000000 -0400
+@@ -0,0 +1,14 @@
++#define DL_SYSDEP_OSRELEASE_CHECK(STR) \
++  do                                                                  \
++    {                                                                 \
++      const char *p;                                                  \
++      for (p = (STR); *p != '\0'; ++p)                                        \
++        if (p[0] == 'x' && p[1] == 'e' && p[2] == 'n' && p[3] == 'U') \
++        {                                                             \
++          GLRO (dl_nosegneg) = 1;                                     \
++          break;                                                      \
++        }                                                             \
++    }                                                                 \
++  while (0)
++
++#include <sysdeps/unix/sysv/linux/dl-osinfo.h>
+--- libc/sysdeps/unix/sysv/linux/dl-osinfo.h.jj        2004-12-16 22:31:50.000000000 -0500
++++ libc/sysdeps/unix/sysv/linux/dl-osinfo.h   2006-10-12 12:23:37.000000000 -0400
+@@ -39,6 +39,9 @@ dl_fatal (const char *str)
+ }
+ #endif
++#ifndef DL_SYSDEP_OSRELEASE_CHECK
++# define DL_SYSDEP_OSRELEASE_CHECK(STR) do { } while (0)
++#endif
+ #define DL_SYSDEP_OSCHECK(FATAL) \
+   do {                                                                              \
+@@ -96,6 +99,8 @@ dl_fatal (const char *str)
+             break;                                                          \
+         }                                                                   \
+                                                                             \
++      DL_SYSDEP_OSRELEASE_CHECK (cp);                                       \
++                                                                            \
+       if (parts < 3)                                                        \
+         version <<= 8 * (3 - parts);                                        \
+                                                                             \
+--- libc/sysdeps/generic/dl-sysdep.c.jj        2004-11-05 19:24:47.000000000 -0500
++++ libc/sysdeps/generic/dl-sysdep.c   2006-10-13 09:02:01.000000000 -0400
+@@ -357,6 +357,9 @@ _dl_important_hwcaps (const char *platfo
+     if ((masked & (1UL << n)) != 0)
+       ++cnt;
++#ifdef DL_ARCH_IMPORTANT_HWCAP
++  cnt += DL_ARCH_IMPORTANT_HWCAP (NULL);
++#endif
+ #ifdef USE_TLS
+   /* For TLS enabled builds always add 'tls'.  */
+   ++cnt;
+@@ -380,6 +383,9 @@ _dl_important_hwcaps (const char *platfo
+   /* Create temporary data structure to generate result table.  */
+   temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp));
+   m = 0;
++#ifdef DL_ARCH_IMPORTANT_HWCAP
++  m += DL_ARCH_IMPORTANT_HWCAP (&temp[m]);
++#endif
+   for (n = 0; masked != 0; ++n)
+     if ((masked & (1UL << n)) != 0)
+       {
+--- libc/sysdeps/generic/dl-cache.c.jj 2004-03-18 19:36:32.000000000 -0500
++++ libc/sysdeps/generic/dl-cache.c    2006-10-13 09:14:44.000000000 -0400
+@@ -261,6 +261,11 @@ _dl_load_cache_lookup (const char *name)
+ #else
+ # define _DL_HWCAP_TLS_MASK 0
+ #endif
++#ifndef DL_ARCH_HWCAP_MASK
++# define DL_ARCH_HWCAP_MASK 0
++#endif
++      uint64_t hwcap_check_mask = ~(GLRO(dl_hwcap) | _DL_HWCAP_PLATFORM
++                                  | _DL_HWCAP_TLS_MASK | DL_ARCH_HWCAP_MASK);
+ #define HWCAP_CHECK \
+       if (GLRO(dl_osversion) && lib->osversion > GLRO(dl_osversion))        \
+       continue;                                                             \
+@@ -268,8 +273,7 @@ _dl_load_cache_lookup (const char *name)
+         && (lib->hwcap & _DL_HWCAP_PLATFORM) != 0                           \
+         && (lib->hwcap & _DL_HWCAP_PLATFORM) != platform)                   \
+       continue;                                                             \
+-      if (lib->hwcap                                                        \
+-        & ~(GLRO(dl_hwcap) | _DL_HWCAP_PLATFORM | _DL_HWCAP_TLS_MASK))      \
++      if (lib->hwcap & hwcap_check_mask)                                    \
+       continue
+       SEARCH_CACHE (cache_new);
+     }
+--- libc/elf/ldconfig.c.jj     2006-09-01 08:10:14.000000000 -0400
++++ libc/elf/ldconfig.c        2006-10-12 12:33:07.000000000 -0400
+@@ -44,6 +44,12 @@
+ #include "dl-procinfo.h"
++#ifdef _DL_FIRST_PLATFORM
++# define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT)
++#else
++# define _DL_FIRST_EXTRA _DL_HWCAP_COUNT
++#endif
++
+ #ifndef LD_SO_CONF
+ # define LD_SO_CONF SYSCONFDIR "/ld.so.conf"
+ #endif
+@@ -115,6 +121,9 @@ static const char *config_file;
+ /* Mask to use for important hardware capabilities.  */
+ static unsigned long int hwcap_mask = HWCAP_IMPORTANT;
++/* Configuration-defined capabilities defined in kernel vDSOs.  */
++static const char *hwcap_extra[64 - _DL_FIRST_EXTRA];
++
+ /* Name and version of program.  */
+ static void print_version (FILE *stream, struct argp_state *state);
+ void (*argp_program_version_hook) (FILE *, struct argp_state *)
+@@ -165,10 +174,10 @@ is_hwcap_platform (const char *name)
+   if (hwcap_idx != -1)
+     return 1;
+-#ifdef USE_TLS
+-  if (strcmp (name, "tls") == 0)
+-    return 1;
+-#endif
++  for (hwcap_idx = _DL_FIRST_EXTRA; hwcap_idx < 64; ++hwcap_idx)
++    if (hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA] != NULL
++      && !strcmp (name, hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA]))
++      return 1;
+   return 0;
+ }
+@@ -203,11 +212,11 @@ path_hwcap (const char *path)
+         h = _dl_string_platform (ptr + 1);
+         if (h == (uint64_t) -1)
+           {
+-#ifdef USE_TLS
+-            if (strcmp (ptr + 1, "tls") == 0)
+-              h = 63;
+-            else
+-#endif
++            for (h = _DL_FIRST_EXTRA; h < 64; ++h)
++              if (hwcap_extra[h - _DL_FIRST_EXTRA] != NULL
++                  && !strcmp (ptr + 1, hwcap_extra[h - _DL_FIRST_EXTRA]))
++                break;
++            if (h == 64)
+               break;
+           }
+       }
+@@ -1039,6 +1048,53 @@ parse_conf (const char *filename, const 
+         memcpy (mempcpy (new_cp, prefix, prefix_len), cp, cp_len + 1);
+         add_dir (new_cp);
+       }
++      else if (!strncasecmp (cp, "hwcap", 5) && isblank (cp[5]))
++      {
++        cp += 6;
++        char *p, *name = NULL;
++        unsigned long int n = strtoul (cp, &cp, 0);
++        if (cp != NULL && isblank (*cp))
++          while ((p = strsep (&cp, " \t")) != NULL)
++            if (p[0] != '\0')
++              {
++                if (name == NULL)
++                  name = p;
++                else
++                  {
++                    name = NULL;
++                    break;
++                  }
++              }
++        if (name == NULL)
++          {
++            error (EXIT_FAILURE, 0, _("%s:%u: bad syntax in hwcap line"),
++                   filename, lineno);
++            break;
++          }
++        if (n >= (64 - _DL_FIRST_EXTRA))
++          error (EXIT_FAILURE, 0,
++                 _("%s:%u: hwcap index %lu above maximum %u"),
++                 filename, lineno, n, 64 - _DL_FIRST_EXTRA - 1);
++        if (hwcap_extra[n] == NULL)
++          {
++            for (unsigned long int h = 0; h < (64 - _DL_FIRST_EXTRA); ++h)
++              if (hwcap_extra[h] != NULL && !strcmp (name, hwcap_extra[h]))
++                error (EXIT_FAILURE, 0,
++                       _("%s:%u: hwcap index %lu already defined as %s"),
++                       filename, lineno, h, name);
++            hwcap_extra[n] = xstrdup (name);
++          }
++        else
++          {
++            if (strcmp (name, hwcap_extra[n]))
++              error (EXIT_FAILURE, 0,
++                     _("%s:%u: hwcap index %lu already defined as %s"),
++                     filename, lineno, n, hwcap_extra[n]);
++            if (opt_verbose)
++              error (0, 0, _("%s:%u: duplicate hwcap %lu %s"),
++                     filename, lineno, n, name);
++          }
++      }
+       else
+       add_dir (cp);
+     }
+@@ -1142,6 +1198,10 @@ main (int argc, char **argv)
+         add_dir (argv[i]);
+     }
++#ifdef USE_TLS
++  hwcap_extra[63 - _DL_FIRST_EXTRA] = "tls";
++#endif
++
+   set_hwcap ();
+   if (opt_chroot)
+--- libc/sysdeps/i386/Makefile 6 Mar 2005 00:18:16 -0000
++++ libc/sysdeps/i386/Makefile 30 Jun 2006 09:16:34 -0000
+@@ -64,4 +64,12 @@ endif
+ ifneq (,$(filter -mno-tls-direct-seg-refs,$(CFLAGS)))
+ defines += -DNO_TLS_DIRECT_SEG_REFS
++else
++# .a libraries are not performance critical and so we
++# build them without direct TLS segment references
++# always.
++CPPFLAGS-.o += -DNO_TLS_DIRECT_SEG_REFS
++CFLAGS-.o += -mno-tls-direct-seg-refs
++CPPFLAGS-.oS += -DNO_TLS_DIRECT_SEG_REFS
++CFLAGS-.oS += -mno-tls-direct-seg-refs
+ endif
diff --git a/src/patches/glibc/glibc-i386-timedrwlock.patch b/src/patches/glibc/glibc-i386-timedrwlock.patch
new file mode 100644 (file)
index 0000000..828bf0e
--- /dev/null
@@ -0,0 +1,97 @@
+2007-07-30  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S
+       (pthread_rwlock_timedrdlock): Copy futex retval to %esi rather than
+       %ecx.
+       * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S
+       (pthread_rwlock_timedwrlock): Likewise.
+       * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S
+       (__pthread_rwlock_unlock): Fix MUTEX != 0 args to __lll_*.
+
+--- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S   27 May 2007 19:19:42 -0000      1.12
++++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S   1 Aug 2007 03:39:45 -0000       1.13
+@@ -124,7 +124,7 @@ pthread_rwlock_timedrdlock:
+       leal    READERS_WAKEUP(%ebp), %ebx
+       movl    $SYS_futex, %eax
+       ENTER_KERNEL
+-      movl    %eax, %ecx
++      movl    %eax, %esi
+ 17:
+       /* Reget the lock.  */
+@@ -139,7 +139,7 @@ pthread_rwlock_timedrdlock:
+       jnz     12f
+ 13:   subl    $1, READERS_QUEUED(%ebp)
+-      cmpl    $-ETIMEDOUT, %ecx
++      cmpl    $-ETIMEDOUT, %esi
+       jne     2b
+ 18:   movl    $ETIMEDOUT, %ecx
+@@ -217,7 +217,7 @@ pthread_rwlock_timedrdlock:
+       call    __lll_mutex_lock_wait
+       jmp     13b
+-16:   movl    $-ETIMEDOUT, %ecx
++16:   movl    $-ETIMEDOUT, %esi
+       jmp     17b
+ 19:   movl    $EINVAL, %ecx
+--- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S   27 May 2007 19:19:42 -0000      1.13
++++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S   1 Aug 2007 03:39:45 -0000       1.14
+@@ -122,7 +122,7 @@ pthread_rwlock_timedwrlock:
+       leal    WRITERS_WAKEUP(%ebp), %ebx
+       movl    $SYS_futex, %eax
+       ENTER_KERNEL
+-      movl    %eax, %ecx
++      movl    %eax, %esi
+ 17:
+       /* Reget the lock.  */
+@@ -137,7 +137,7 @@ pthread_rwlock_timedwrlock:
+       jnz     12f
+ 13:   subl    $1, WRITERS_QUEUED(%ebp)
+-      cmpl    $-ETIMEDOUT, %ecx
++      cmpl    $-ETIMEDOUT, %esi
+       jne     2b
+ 18:   movl    $ETIMEDOUT, %ecx
+@@ -210,7 +210,7 @@ pthread_rwlock_timedwrlock:
+       call    __lll_mutex_lock_wait
+       jmp     13b
+-16:   movl    $-ETIMEDOUT, %ecx
++16:   movl    $-ETIMEDOUT, %esi
+       jmp     17b
+ 19:   movl    $EINVAL, %ecx
+--- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S        27 May 2007 19:19:42 -0000      1.9
++++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S        1 Aug 2007 03:39:57 -0000       1.10
+@@ -117,7 +117,7 @@ __pthread_rwlock_unlock:
+ #if MUTEX == 0
+       movl    %edi, %ecx
+ #else
+-      leal    MUTEX(%edx), %ecx
++      leal    MUTEX(%edi), %ecx
+ #endif
+       call    __lll_mutex_lock_wait
+       jmp     2b
+@@ -126,7 +126,7 @@ __pthread_rwlock_unlock:
+ #if MUTEX == 0
+       movl    %edi, %eax
+ #else
+-      leal    MUTEX(%edx), %eax
++      leal    MUTEX(%edi), %eax
+ #endif
+       call    __lll_mutex_unlock_wake
+       jmp     4b
+@@ -135,7 +135,7 @@ __pthread_rwlock_unlock:
+ #if MUTEX == 0
+       movl    %edi, %eax
+ #else
+-      leal    MUTEX(%edx), %eax
++      leal    MUTEX(%edi), %eax
+ #endif
+       call    __lll_mutex_unlock_wake
+       jmp     8b
diff --git a/src/patches/glibc/glibc-i686-memset.patch b/src/patches/glibc/glibc-i686-memset.patch
new file mode 100644 (file)
index 0000000..d435b28
--- /dev/null
@@ -0,0 +1,31 @@
+2006-02-21  Roland McGrath  <roland@redhat.com>
+
+       * sysdeps/i386/i686/memset.S: Fix treatment of unaligned pointer.
+       Reported by John Zulauf <john.zulauf@amd.com>.
+
+--- libc/sysdeps/i386/i686/memset.S    4 May 2005 06:21:50 -0000       1.9
++++ libc/sysdeps/i386/i686/memset.S    22 Feb 2006 02:39:06 -0000      1.10
+@@ -64,17 +64,17 @@ ENTRY (BP_SYM (memset))
+       movl    %edx, %edi
+       cfi_rel_offset (edi, 0)
+       andl    $3, %edx
+-      jz      2f
+-      jnp     3f
+-      stosb
++      jz      2f      /* aligned */
++      jp      3f      /* misaligned at 3, store just one byte below */
++      stosb           /* misaligned at 1 or 2, store two bytes */
+       decl    %ecx
+       jz      1f
+ 3:    stosb
+       decl    %ecx
+       jz      1f
+-      xorl    $3, %edx
+-      jz      2f
+-      stosb
++      xorl    $1, %edx
++      jnz     2f      /* was misaligned at 2 or 3, now aligned */
++      stosb           /* was misaligned at 1, store third byte */
+       decl    %ecx
+ 2:    movl    %ecx, %edx
+       shrl    $2, %ecx
diff --git a/src/patches/glibc/glibc-ia64-lib64.patch b/src/patches/glibc/glibc-ia64-lib64.patch
new file mode 100644 (file)
index 0000000..05fd922
--- /dev/null
@@ -0,0 +1,92 @@
+2004-05-14  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/configure.in: Use */lib64 even for ia64.
+       * sysdeps/unix/sysv/linux/configure: Rebuilt.
+       * sysdeps/unix/sysv/linux/ia64/dl-procinfo.c: New file.
+       * sysdeps/unix/sysv/linux/ia64/dl-procinfo.h: New file.
+       * sysdeps/unix/sysv/linux/ia64/ldd-rewrite.sed: Change /lib64/ld*
+       into /lib/ld*.  Add LD_LIBRARY_VERSION.
+       * sysdeps/unix/sysv/linux/ia64/ldconfig.h
+       (SYSDEP_KNOWN_INTERPRETER_NAMES): Add /lib64/ld-linux-ia64.so.2.
+       * sysdeps/unix/sysv/linux/ia64/dl-cache.h: Include sparc-linux
+       dl-cache.h instead of generic dl-cache.h.
+
+--- libc/sysdeps/unix/sysv/linux/configure.jj  2003-03-23 03:10:04.000000000 +0100
++++ libc/sysdeps/unix/sysv/linux/configure     2004-05-14 15:54:35.669802684 +0200
+@@ -225,7 +225,7 @@ case "$prefix" in
+   # 64-bit libraries on bi-arch platforms go in /lib64 instead of /lib
+   case $machine in
+   sparc/sparc64 | x86_64 | powerpc/powerpc64 | s390/s390-64 | \
+-  mips/mips64/n64/* )
++  mips/mips64/n64/* | ia64 )
+     libc_cv_slibdir="/lib64"
+     if test "$libdir" = '${exec_prefix}/lib'; then
+       libdir='${exec_prefix}/lib64';
+--- libc/sysdeps/unix/sysv/linux/configure.in.jj       2003-03-23 03:10:04.000000000 +0100
++++ libc/sysdeps/unix/sysv/linux/configure.in  2004-05-14 15:53:44.355998785 +0200
+@@ -158,7 +158,7 @@ case "$prefix" in
+   # 64-bit libraries on bi-arch platforms go in /lib64 instead of /lib
+   case $machine in
+   sparc/sparc64 | x86_64 | powerpc/powerpc64 | s390/s390-64 | \
+-  mips/mips64/n64/* )
++  mips/mips64/n64/* | ia64 )
+     libc_cv_slibdir="/lib64"
+     if test "$libdir" = '${exec_prefix}/lib'; then
+       libdir='${exec_prefix}/lib64';
+--- libc/sysdeps/unix/sysv/linux/ia64/dl-procinfo.c.jj 2004-05-14 15:42:09.307560515 +0200
++++ libc/sysdeps/unix/sysv/linux/ia64/dl-procinfo.c    2003-09-30 00:23:24.000000000 +0200
+@@ -0,0 +1,5 @@
++#ifdef IS_IN_ldconfig
++#include <sysdeps/i386/dl-procinfo.c>
++#else
++#include <sysdeps/generic/dl-procinfo.c>
++#endif
+--- libc/sysdeps/unix/sysv/linux/ia64/ldd-rewrite.sed.jj       2002-01-17 07:49:28.000000000 +0100
++++ libc/sysdeps/unix/sysv/linux/ia64/ldd-rewrite.sed  2004-05-14 16:21:03.041325040 +0200
+@@ -1 +1,4 @@
+-s_^\(RTLDLIST=\)\([^  ]*\)-ia64\(\.so\.[0-9.]*\)[     ]*$_\1"\2-ia64\3 \2\3"_
++/LD_TRACE_LOADED_OBJECTS=1/a\
++add_env="$add_env LD_LIBRARY_VERSION=\\$verify_out"
++s_^\(RTLDLIST=\)/lib64/ld\([^         ]*\)-ia64\(\.so\.[0-9.]*\)[     ]*$_\1"/lib/ld\2-ia64\3 /lib/ld\2\3"_
++s_^\(RTLDLIST=\)\([^"][^      ]*\)-ia64\(\.so\.[0-9.]*\)[     ]*$_\1"\2-ia64\3 \2\3"_
+--- libc/sysdeps/unix/sysv/linux/ia64/ldconfig.h.jj    2001-07-06 06:56:17.000000000 +0200
++++ libc/sysdeps/unix/sysv/linux/ia64/ldconfig.h       2004-05-14 15:45:40.103783087 +0200
+@@ -1,4 +1,4 @@
+-/* Copyright (C) 2001 Free Software Foundation, Inc.
++/* Copyright (C) 2001, 2004 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 @@
+ #include <sysdeps/generic/ldconfig.h>
+ #define SYSDEP_KNOWN_INTERPRETER_NAMES \
+-  { "/lib/ld-linux.so.2", FLAG_ELF_LIBC6 },
++  { "/lib/ld-linux.so.2", FLAG_ELF_LIBC6 }, \
++  { "/lib64/ld-linux-ia64.so.2", FLAG_ELF_LIBC6 },
+ #define SYSDEP_KNOWN_LIBRARY_NAMES \
+   { "libc.so.6", FLAG_ELF_LIBC6 },    \
+   { "libm.so.6", FLAG_ELF_LIBC6 },
+--- libc/sysdeps/unix/sysv/linux/ia64/dl-cache.h.jj    2001-07-06 06:56:17.000000000 +0200
++++ libc/sysdeps/unix/sysv/linux/ia64/dl-cache.h       2004-05-14 15:41:11.658891907 +0200
+@@ -1,5 +1,5 @@
+ /* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
+-   Copyright (C) 2000 Free Software Foundation, Inc.
++   Copyright (C) 2000, 2004 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,4 +22,4 @@
+ #define _dl_cache_check_flags(flags) \
+   ((flags) == _DL_CACHE_DEFAULT_ID)
+-#include_next <dl-cache.h>
++#include <sysdeps/unix/sysv/linux/sparc/dl-cache.h>
+--- libc/sysdeps/unix/sysv/linux/ia64/dl-procinfo.h.jj 2004-05-14 15:42:13.018895395 +0200
++++ libc/sysdeps/unix/sysv/linux/ia64/dl-procinfo.h    2003-07-23 00:06:23.000000000 +0200
+@@ -0,0 +1,5 @@
++#ifdef IS_IN_ldconfig
++#include <sysdeps/unix/sysv/linux/i386/dl-procinfo.h>
++#else
++#include <sysdeps/generic/dl-procinfo.h>
++#endif
diff --git a/src/patches/glibc/glibc-ia64-libm-error.patch b/src/patches/glibc/glibc-ia64-libm-error.patch
new file mode 100644 (file)
index 0000000..a0ffdd3
--- /dev/null
@@ -0,0 +1,35 @@
+2005-08-19  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * sysdeps/ia64/fpu/libm_error.c (__libm_error_support): Don't abort.
+
+--- libc/sysdeps/ia64/fpu/libm_error.c 5 Apr 2005 22:34:12 -0000       1.5
++++ libc/sysdeps/ia64/fpu/libm_error.c 20 Aug 2005 01:21:16 -0000      1.6
+@@ -81,8 +81,8 @@
+ // 12/13/04: Corrected POSIX behavior for exp2_overflow, exp2_underflow,
+ //           exp10_overflow, exp10_underflow.  Added ISOC to set errno for
+ //           exp10_underflow.
+-// 12/14/04: Corrected POSIX behavior for nextafter_overflow, 
+-//           nextafter_underflow, nexttoward_overflow, nexttoward_underflow.  
++// 12/14/04: Corrected POSIX behavior for nextafter_overflow,
++//           nextafter_underflow, nexttoward_overflow, nexttoward_underflow.
+ //           Added ISOC to set errno for nextafter and nexttoward underflow.
+ // 12/15/04: Corrected POSIX behavior for exp, exp2, and exp10 underflow.
+ // 03/31/05: Added missing ALIGNIT statement to 6 float constants.
+@@ -674,7 +674,7 @@ else if(_LIB_VERSIONIMF==_ISOC_)
+          ERRNO_DOMAIN; break;
+     }
+     default:
+-      abort();
++      break;
+    }
+    return;
+ }
+@@ -1374,7 +1374,7 @@ switch(input_tag)
+       ERRNO_RANGE; break;
+    }
+   default:
+-    abort();
++    break;
+ }
+ return;
+ /* _POSIX_ */
diff --git a/src/patches/glibc/glibc-ia64-mcount.patch b/src/patches/glibc/glibc-ia64-mcount.patch
new file mode 100644 (file)
index 0000000..f9df4d4
--- /dev/null
@@ -0,0 +1,30 @@
+2005-03-21  David Mosberger  <davidm@hpl.hp.com>
+
+       * sysdeps/ia64/_mcount.S: Newer kernels don't like register-frames
+       with more than 8 output registers.  Fix this by passing original
+       ar.pfs to _mcount_ret_helper via r3.
+
+--- libc/sysdeps/ia64/_mcount.S        6 Jul 2001 04:55:54 -0000       1.4
++++ libc/sysdeps/ia64/_mcount.S        22 Mar 2005 09:06:17 -0000      1.5
+@@ -72,6 +72,7 @@ LEAF(_mcount)
+       mov b7 = loc0
+       mov rp = in2
+       ;;
++      mov r3 = in0
+       mov r8 = loc2
+       mov r15 = loc3
+       mov b6 = r2
+@@ -81,10 +82,10 @@ END(_mcount)
+ LOCAL_LEAF(_mcount_ret_helper)
+       .prologue
+       .altrp b7
+-      .save ar.pfs, r40
++      .save ar.pfs, r3
+       .body
+-      alloc r2 = ar.pfs, 0, 0, 9, 0
+-      mov ar.pfs = r40
++      alloc r2 = ar.pfs, 0, 0, 8, 0
++      mov ar.pfs = r3
+       br b7
+ END(_mcount_ret_helper)
diff --git a/src/patches/glibc/glibc-ia64-post-upgrade-hack.patch b/src/patches/glibc/glibc-ia64-post-upgrade-hack.patch
new file mode 100644 (file)
index 0000000..2545797
--- /dev/null
@@ -0,0 +1,61 @@
+--- libc/fedora/glibc_post_upgrade.c.jj        2004-12-20 02:59:25.000000000 -0500
++++ libc/fedora/glibc_post_upgrade.c   2005-06-14 10:54:32.000000000 -0400
+@@ -27,6 +27,39 @@ __attribute__((noinline)) void sayn (lon
+ __attribute__((noinline)) void message (char *const path[]);
+ __attribute__((noinline)) int check_elf (const char *name);
++#ifdef __i386__
++static int
++is_ia64 (void)
++{
++  unsigned int fl1, fl2;
++
++  /* See if we can use cpuid.  */
++  __asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
++         "pushl %0; popfl; pushfl; popl %0; popfl"
++         : "=&r" (fl1), "=&r" (fl2)
++         : "i" (0x00200000));
++  if (((fl1 ^ fl2) & 0x00200000) == 0)
++    return 0;
++
++  /* Host supports cpuid.  See if cpuid gives capabilities, try
++     CPUID(0).  Preserve %ebx and %ecx; cpuid insn clobbers these, we
++     don't need their CPUID values here, and %ebx may be the PIC
++     register.  */
++  __asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx"
++         : "=a" (fl1) : "0" (0) : "edx", "cc");
++  if (fl1 == 0)
++    return 0;
++
++  /* Invoke CPUID(1), return %edx; caller can examine bits to
++     determine what's supported.  */
++  __asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx"
++         : "=d" (fl2), "=a" (fl1) : "1" (1) : "cc");
++  return (fl2 & (1 << 30)) != 0;
++}
++#else
++#define is_ia64() 0
++#endif
++
+ int
+ main (void)
+ {
+@@ -162,9 +195,16 @@ main (void)
+ #ifndef ICONVCONFIG
+ #define ICONVCONFIG "/usr/sbin/iconvconfig"
+ #endif
++      const char *iconv_cache = GCONV_MODULES_DIR"/gconv-modules.cache";
++      const char *iconv_dir = GCONV_MODULES_DIR;
++      if (is_ia64 ())
++      {
++        iconv_cache = "/emul/ia32-linux"GCONV_MODULES_DIR"/gconv-modules.cache";
++        iconv_dir = "/emul/ia32-linux"GCONV_MODULES_DIR;
++      }
+       verbose_exec (113, ICONVCONFIG, "/usr/sbin/iconvconfig",
+-                  "-o", GCONV_MODULES_DIR"/gconv-modules.cache",
+-                  "--nostdlib", GCONV_MODULES_DIR);
++                  "-o", iconv_cache,
++                  "--nostdlib", iconv_dir);
+     }
+   /* Check if telinit is available and the init fifo as well.  */
diff --git a/src/patches/glibc/glibc-ia64-shmatt_t.patch b/src/patches/glibc/glibc-ia64-shmatt_t.patch
new file mode 100644 (file)
index 0000000..4d78ebe
--- /dev/null
@@ -0,0 +1,25 @@
+2005-11-19  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/ia64/bits/shm.h (shmatt_t): New type.
+       (struct shmid_ds): Use it for shm_nattch field.
+
+--- libc/sysdeps/unix/sysv/linux/ia64/bits/shm.h       20 Dec 2002 10:31:09 -0000      1.5
++++ libc/sysdeps/unix/sysv/linux/ia64/bits/shm.h       19 Nov 2005 17:17:15 -0000      1.6
+@@ -38,6 +38,8 @@
+ /* Segment low boundary address multiple.  */
+ #define SHMLBA                (1024 * 1024)
++/* Type to count number of attaches.  */
++typedef unsigned long int shmatt_t;
+ /* Data structure describing a set of semaphores.  */
+ struct shmid_ds
+@@ -49,7 +51,7 @@ struct shmid_ds
+     __time_t shm_ctime;                       /* time of last change by shmctl() */
+     __pid_t shm_cpid;                 /* pid of creator */
+     __pid_t shm_lpid;                 /* pid of last shmop */
+-    unsigned long int shm_nattch;     /* number of current attaches */
++    shmatt_t shm_nattch;              /* number of current attaches */
+     unsigned long int __unused1;
+     unsigned long int __unused2;
+   };
diff --git a/src/patches/glibc/glibc-innetgr-leak.patch b/src/patches/glibc/glibc-innetgr-leak.patch
new file mode 100644 (file)
index 0000000..a7243e5
--- /dev/null
@@ -0,0 +1,35 @@
+2005-09-24  Jakub Jelinek  <jakub@redhat.com>
+
+       * inet/getnetgrent_r.c (innetgr): Call endfct even if result != 0.
+       Return 1 only if result == 1.  Patch by Benoit Capelle.
+
+--- libc/inet/getnetgrent_r.c  10 Sep 2005 03:16:29 -0000      1.29
++++ libc/inet/getnetgrent_r.c  25 Sep 2005 22:54:19 -0000      1.30
+@@ -409,9 +409,6 @@ innetgr (const char *netgroup, const cha
+                   }
+               }
+-            if (result != 0)
+-              break;
+-
+             /* If we found one service which does know the given
+                netgroup we don't try further.  */
+             status = NSS_STATUS_RETURN;
+@@ -422,6 +419,9 @@ innetgr (const char *netgroup, const cha
+         if (endfct != NULL)
+           (*endfct) (&entry);
++        if (result != 0)
++          break;
++
+         /* Look for the next service.  */
+         no_more = __nss_next (&entry.nip, "setnetgrent",
+                               &setfct.ptr, status, 0);
+@@ -444,6 +444,6 @@ innetgr (const char *netgroup, const cha
+   /* Free the memory.  */
+   free_memory (&entry);
+-  return result;
++  return result == 1;
+ }
+ libc_hidden_def (innetgr)
diff --git a/src/patches/glibc/glibc-innetgr-thread-safety.patch b/src/patches/glibc/glibc-innetgr-thread-safety.patch
new file mode 100644 (file)
index 0000000..0e586da
--- /dev/null
@@ -0,0 +1,411 @@
+2005-09-09  Jakub Jelinek  <jakub@redhat.com>
+
+       * inet/getnetgrent_r.c: Include assert.
+       (setup): Remove FUNC_NAME and ALL arguments, assume they are always
+       "setnetgrent" and 1.
+       (endnetgrent_hook): New function.
+       (internal_endnetgrent): Use it.
+       (__internal_setnetgrent_reuse): Use it.  Adjust setup caller.
+       If status is NSS_STATUS_SUCCESS, yet action is continue, call
+       endnetgrent hook.
+       (internal_getnetgrent_r): Use __nss_lookup_function rather than
+       setup.  Recompute getfct pointer after successful
+       __internal_setnetgrent_reuse.  Don't use __nss_next.
+       (innetgr): Use __nss_lookup_function instead of __nss_lookup.
+       Adjust setup caller.
+       * nss/nss_files/files-netgrp.c (_nss_files_endnetgrent): Always clear
+       data_size and cursor.  Add libnss_files_hidden_proto and
+       libnss_files_hidden_def.
+       (_nss_files_setnetgrent): Call _nss_files_endnetgrent on failure.
+       * nis/nss_nis/nis-netgrp.c (internal_endnetgrent): Always clear
+       data_size and cursor.
+       (_nss_nis_setnetgrent): Don't call internal_endnetgrent.
+       (_nss_nis_getnetgrent_r): Remove result->cursor == NULL handling.
+       * nis/nss_nisplus/nisplus-netgrp.c (internal_endnetgrent): Always clear
+       data_size and position.
+       (_nss_nisplus_setnetgrent): Don't call internal_endnetgrent.
+
+2005-09-09  Ulrich Drepper  <drepper@redhat.com>
+
+       * nss/nss_files/files-netgrp.c (_nss_files_setnetgrent): We don't
+       need locking for the stream.  Use feof_unlocked.
+
+--- libc/inet/getnetgrent_r.c  14 Aug 2004 04:16:22 -0000      1.28
++++ libc/inet/getnetgrent_r.c  10 Sep 2005 03:16:29 -0000      1.29
+@@ -16,6 +17,7 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
++#include <assert.h>
+ #include <bits/libc-lock.h>
+ #include <errno.h>
+ #include <netdb.h>
+@@ -33,15 +35,13 @@ __libc_lock_define_initialized (static, 
+ static struct __netgrent dataset;
+ /* The lookup function for the first entry of this service.  */
+-extern int __nss_netgroup_lookup (service_user **nip, const char *name,
++extern int __nss_netgroup_lookup (service_user **nipp, const char *name,
+                                 void **fctp) internal_function;
+-
+-/* Set up NIP to run through the services.  If ALL is zero, use NIP's
+-   current location if it's not nil.  Return nonzero if there are no
++/* Set up NIP to run through the services.  Return nonzero if there are no
+    services (left).  */
+-static enum nss_status
+-setup (void **fctp, const char *func_name, int all, service_user **nipp)
++static int
++setup (void **fctp, service_user **nipp)
+ {
+   /* Remember the first service_entry, it's always the same.  */
+   static service_user *startp;
+@@ -51,7 +51,7 @@ setup (void **fctp, const char *func_nam
+     {
+       /* Executing this more than once at the same time must yield the
+        same result every time.  So we need no locking.  */
+-      no_more = __nss_netgroup_lookup (nipp, func_name, fctp);
++      no_more = __nss_netgroup_lookup (nipp, "setnetgrent", fctp);
+       startp = no_more ? (service_user *) -1 : *nipp;
+     }
+   else if (startp == (service_user *) -1)
+@@ -59,11 +59,10 @@ setup (void **fctp, const char *func_nam
+     return 1;
+   else
+     {
+-      if (all || *nipp == NULL)
+-      /* Reset to the beginning of the service list.  */
+-      *nipp = startp;
++      /* Reset to the beginning of the service list.  */
++      *nipp = startp;
+       /* Look up the first function.  */
+-      no_more = __nss_lookup (nipp, func_name, fctp);
++      no_more = __nss_lookup (nipp, "setnetgrent", fctp);
+     }
+   return no_more;
+ }
+@@ -87,6 +86,20 @@ free_memory (struct __netgrent *data)
+     }
+ }
\f
++static void
++endnetgrent_hook (struct __netgrent *datap)
++{
++  enum nss_status (*endfct) (struct __netgrent *);
++
++  if (datap->nip == NULL)
++    return;
++
++  endfct = __nss_lookup_function (datap->nip, "endnetgrent");
++  if (endfct != NULL)
++    (void) (*endfct) (datap);
++  datap->nip = NULL;
++}
++
+ static int
+ internal_function
+ __internal_setnetgrent_reuse (const char *group, struct __netgrent *datap,
+@@ -100,14 +113,29 @@ __internal_setnetgrent_reuse (const char
+   enum nss_status status = NSS_STATUS_UNAVAIL;
+   struct name_list *new_elem;
++  /* Free data from previous service.  */
++  endnetgrent_hook (datap);
++
+   /* Cycle through all the services and run their setnetgrent functions.  */
+-  int no_more = setup (&fct.ptr, "setnetgrent", 1, &datap->nip);
++  int no_more = setup (&fct.ptr, &datap->nip);
+   while (! no_more)
+     {
++      assert (datap->data == NULL);
++
+       /* Ignore status, we force check in `__nss_next'.  */
+       status = (*fct.f) (group, datap);
++      service_user *old_nip = datap->nip;
+       no_more = __nss_next (&datap->nip, "setnetgrent", &fct.ptr, status, 0);
++
++      if (status == NSS_STATUS_SUCCESS && ! no_more)
++      {
++        enum nss_status (*endfct) (struct __netgrent *);
++
++        endfct = __nss_lookup_function (old_nip, "endnetgrent");
++        if (endfct != NULL)
++          (void) (*endfct) (datap);
++      }
+     }
+   /* Add the current group to the list of known groups.  */
+@@ -157,34 +185,13 @@ setnetgrent (const char *group)
+   return result;
+ }
+-
+ void internal_endnetgrent (struct __netgrent *datap);
+ libc_hidden_proto (internal_endnetgrent)
+ void
+ internal_endnetgrent (struct __netgrent *datap)
+ {
+-  service_user *old_nip;
+-  union
+-  {
+-    enum nss_status (*f) (struct __netgrent *);
+-    void *ptr;
+-  } fct;
+-
+-  /* Remember which was the last used service.  */
+-  old_nip = datap->nip;
+-
+-  /* Cycle through all the services and run their endnetgrent functions.  */
+-  int no_more = setup (&fct.ptr, "endnetgrent", 1, &datap->nip);
+-  while (! no_more)
+-    {
+-      /* Ignore status, we force check in `__nss_next'.  */
+-      (void) (*fct.f) (datap);
+-
+-      no_more = (datap->nip == old_nip
+-               || __nss_next (&datap->nip, "endnetgrent", &fct.ptr, 0, 1));
+-    }
+-
++  endnetgrent_hook (datap);
+   /* Now free list of all netgroup names from last run.  */
+   free_memory (datap);
+ }
+@@ -213,11 +220,7 @@ internal_getnetgrent_r (char **hostp, ch
+                         struct __netgrent *datap,
+                         char *buffer, size_t buflen, int *errnop)
+ {
+-  union
+-  {
+-    enum nss_status (*f) (struct __netgrent *, char *, size_t, int *);
+-    void *ptr;
+-  } fct;
++  enum nss_status (*fct) (struct __netgrent *, char *, size_t, int *);
+   /* Initialize status to return if no more functions are found.  */
+   enum nss_status status = NSS_STATUS_NOTFOUND;
+@@ -225,10 +228,12 @@ internal_getnetgrent_r (char **hostp, ch
+   /* Run through available functions, starting with the same function last
+      run.  We will repeat each function as long as it succeeds, and then go
+      on to the next service action.  */
+-  int no_more = setup (&fct.ptr, "getnetgrent_r", 0, &datap->nip);
++  int no_more = (datap->nip == NULL
++               || (fct = __nss_lookup_function (datap->nip, "getnetgrent_r"))
++                  == NULL);
+   while (! no_more)
+     {
+-      status = (*fct.f) (datap, buffer, buflen, &errno);
++      status = (*fct) (datap, buffer, buflen, &errno);
+       if (status == NSS_STATUS_RETURN)
+       {
+@@ -246,8 +251,12 @@ internal_getnetgrent_r (char **hostp, ch
+                                                   datap, errnop);
+           }
+-        if (found)
+-          continue;
++        if (found && datap->nip != NULL)
++          {
++            fct = __nss_lookup_function (datap->nip, "getnetgrent_r");
++            if (fct != NULL)
++              continue;
++          }
+       }
+       else if (status == NSS_STATUS_SUCCESS && datap->type == group_val)
+       {
+@@ -279,7 +288,7 @@ internal_getnetgrent_r (char **hostp, ch
+           }
+       }
+-      no_more = __nss_next (&datap->nip, "getnetgrent_r", &fct.ptr, status, 0);
++      break;
+     }
+   if (status == NSS_STATUS_SUCCESS)
+@@ -322,16 +331,8 @@ innetgr (const char *netgroup, const cha
+     int (*f) (const char *, struct __netgrent *);
+     void *ptr;
+   } setfct;
+-  union
+-  {
+-    void (*f) (struct __netgrent *);
+-    void *ptr;
+-  } endfct;
+-  union
+-  {
+-    int (*f) (struct __netgrent *, char *, size_t, int *);
+-    void *ptr;
+-  } getfct;
++  void (*endfct) (struct __netgrent *);
++  int (*getfct) (struct __netgrent *, char *, size_t, int *);
+   struct __netgrent entry;
+   int result = 0;
+   const char *current_group = netgroup;
+@@ -345,18 +346,21 @@ innetgr (const char *netgroup, const cha
+      the work during one walk through the service list.  */
+   while (1)
+     {
+-      int no_more = setup (&setfct.ptr, "setnetgrent", 1, &entry.nip);
++      int no_more = setup (&setfct.ptr, &entry.nip);
+       while (! no_more)
+       {
++        assert (entry.data == NULL);
++
+         /* Open netgroup.  */
+         enum nss_status status = (*setfct.f) (current_group, &entry);
+         if (status == NSS_STATUS_SUCCESS
+-            && __nss_lookup (&entry.nip, "getnetgrent_r", &getfct.ptr) == 0)
++            && (getfct = __nss_lookup_function (entry.nip, "getnetgrent_r"))
++               != NULL)
+           {
+             char buffer[1024];
+-            while ((*getfct.f) (&entry, buffer, sizeof buffer, &errno)
++            while ((*getfct) (&entry, buffer, sizeof buffer, &errno)
+                    == NSS_STATUS_SUCCESS)
+               {
+                 if (entry.type == group_val)
+@@ -414,8 +418,9 @@ innetgr (const char *netgroup, const cha
+           }
+         /* Free all resources of the service.  */
+-        if (__nss_lookup (&entry.nip, "endnetgrent", &endfct.ptr) == 0)
+-          (*endfct.f) (&entry);
++        endfct = __nss_lookup_function (entry.nip, "endnetgrent");
++        if (endfct != NULL)
++          (*endfct) (&entry);
+         /* Look for the next service.  */
+         no_more = __nss_next (&entry.nip, "setnetgrent",
+--- libc/nis/nss_nisplus/nisplus-netgrp.c      10 Dec 2004 10:43:30 -0000      1.14
++++ libc/nis/nss_nisplus/nisplus-netgrp.c      10 Sep 2005 03:18:49 -0000      1.15
+@@ -141,13 +141,10 @@ _nss_nisplus_getnetgrent_r (struct __net
+ static void
+ internal_endnetgrent (struct __netgrent *netgrp)
+ {
+-  if (netgrp->data != NULL)
+-    {
+-      nis_freeresult ((nis_result *) netgrp->data);
+-      netgrp->data = NULL;
+-      netgrp->data_size = 0;
+-      netgrp->position = 0;
+-    }
++  nis_freeresult ((nis_result *) netgrp->data);
++  netgrp->data = NULL;
++  netgrp->data_size = 0;
++  netgrp->position = 0;
+ }
+ enum nss_status
+@@ -161,8 +158,6 @@ _nss_nisplus_setnetgrent (const char *gr
+   status = NSS_STATUS_SUCCESS;
+-  internal_endnetgrent (netgrp);
+-
+   sprintf (buf, "[name=%s],netgroup.org_dir", group);
+   netgrp->data = (char *) nis_list (buf, EXPAND_NAME, NULL, NULL);
+--- libc/nis/nss_nis/nis-netgrp.c      16 Aug 2005 16:04:13 -0000      1.13
++++ libc/nis/nss_nis/nis-netgrp.c      10 Sep 2005 03:19:20 -0000      1.14
+@@ -41,13 +41,10 @@ _nss_netgroup_parseline (char **cursor, 
+ static void
+ internal_nis_endnetgrent (struct __netgrent *netgrp)
+ {
+-  if (netgrp->data != NULL)
+-    {
+-      free (netgrp->data);
+-      netgrp->data = NULL;
+-      netgrp->data_size = 0;
+-      netgrp->cursor = NULL;
+-    }
++  free (netgrp->data);
++  netgrp->data = NULL;
++  netgrp->data_size = 0;
++  netgrp->cursor = NULL;
+ }
+ enum nss_status
+@@ -65,8 +62,6 @@ _nss_nis_setnetgrent (const char *group,
+   if (yp_get_default_domain (&domain))
+     return NSS_STATUS_UNAVAIL;
+-  internal_nis_endnetgrent (netgrp);
+-
+   status = yperr2nss (yp_match (domain, "netgroup", group, strlen (group),
+                               &netgrp->data, &len));
+   if (status == NSS_STATUS_SUCCESS)
+@@ -99,9 +94,6 @@ enum nss_status
+ _nss_nis_getnetgrent_r (struct __netgrent *result, char *buffer, size_t buflen,
+                       int *errnop)
+ {
+-  if (result->cursor == NULL)
+-    return NSS_STATUS_NOTFOUND;
+-
+   return _nss_netgroup_parseline (&result->cursor, result, buffer, buflen,
+                                 errnop);
+ }
+--- libc/nss/nss_files/files-netgrp.c  24 Oct 2004 09:05:12 -0000      1.13
++++ libc/nss/nss_files/files-netgrp.c  10 Sep 2005 00:06:32 -0000      1.14
+@@ -22,6 +22,7 @@
+ #include <errno.h>
+ #include <netdb.h>
+ #include <stdio.h>
++#include <stdio_ext.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include "nsswitch.h"
+@@ -29,6 +30,7 @@
+ #define DATAFILE      "/etc/netgroup"
++libnss_files_hidden_proto (_nss_files_endnetgrent)
+ #define EXPAND(needed)                                                              \
+   do                                                                        \
+@@ -75,7 +77,9 @@ _nss_files_setnetgrent (const char *grou
+       status = NSS_STATUS_NOTFOUND;
+       result->cursor = result->data;
+-      while (!feof (fp))
++      __fsetlocking (fp, FSETLOCKING_BYCALLER);
++
++      while (!feof_unlocked (fp))
+       {
+         ssize_t curlen = getline (&line, &line_len, fp);
+         int found;
+@@ -140,6 +144,9 @@ _nss_files_setnetgrent (const char *grou
+       /* We don't need the file and the line buffer anymore.  */
+       free (line);
+       fclose (fp);
++
++      if (status != NSS_STATUS_SUCCESS)
++      _nss_files_endnetgrent (result);
+     }
+   return status;
+@@ -150,16 +157,13 @@ int
+ _nss_files_endnetgrent (struct __netgrent *result)
+ {
+   /* Free allocated memory for data if some is present.  */
+-  if (result->data != NULL)
+-    {
+-      free (result->data);
+-      result->data = NULL;
+-      result->data_size = 0;
+-      result->cursor = NULL;
+-    }
+-
++  free (result->data);
++  result->data = NULL;
++  result->data_size = 0;
++  result->cursor = NULL;
+   return NSS_STATUS_SUCCESS;
+ }
++libnss_files_hidden_def (_nss_files_endnetgrent)
+ static char *
+ strip_whitespace (char *str)
diff --git a/src/patches/glibc/glibc-ld-library-path-DST.patch b/src/patches/glibc/glibc-ld-library-path-DST.patch
new file mode 100644 (file)
index 0000000..1d60cb6
--- /dev/null
@@ -0,0 +1,33 @@
+2006-08-28  Ulrich Drepper  <drepper@redhat.com>
+
+       * elf/dl-load.c (_dl_init_paths): Expand DSTs.
+
+--- libc/elf/dl-load.c 27 Jun 2006 14:23:02 -0000      1.278
++++ libc/elf/dl-load.c 29 Aug 2006 01:43:42 -0000      1.279
+@@ -749,7 +749,25 @@ _dl_init_paths (const char *llp)
+     {
+       size_t nllp;
+       const char *cp = llp;
+-      char *llp_tmp = strdupa (llp);
++      char *llp_tmp;
++
++#ifdef SHARED
++      /* Expand DSTs.  */
++      size_t cnt = DL_DST_COUNT (llp, 1);
++      if (__builtin_expect (cnt == 0, 1))
++      llp_tmp = strdupa (llp);
++      else
++      {
++        /* Determine the length of the substituted string.  */
++        size_t total = DL_DST_REQUIRED (l, llp, strlen (llp), cnt);
++
++        /* Allocate the necessary memory.  */
++        llp_tmp = (char *) alloca (total + 1);
++        llp_tmp = _dl_dst_substitute (l, llp, llp_tmp, 1);
++      }
++#else
++      llp_tmp = strdupa (llp);
++#endif
+       /* Decompose the LD_LIBRARY_PATH contents.  First determine how many
+        elements it has.  */
diff --git a/src/patches/glibc/glibc-ld_debug-conflicts.patch b/src/patches/glibc/glibc-ld_debug-conflicts.patch
new file mode 100644 (file)
index 0000000..2711bf3
--- /dev/null
@@ -0,0 +1,19 @@
+2005-10-26  Jakub Jelinek  <jakub@redhat.com>
+
+       * elf/dl-conflict.c (_dl_resolve_conflicts): Use _dl_debug_printf
+       instead of _dl_printf to print conflict processing debug message.
+       Reported by John Reiser <jreiser@BitWagon.com>.
+
+--- libc/elf/dl-conflict.c     14 Oct 2004 01:53:55 -0000      1.12
++++ libc/elf/dl-conflict.c     31 Oct 2005 01:28:48 -0000      1.13
+@@ -34,8 +34,8 @@ _dl_resolve_conflicts (struct link_map *
+ {
+ #if ! ELF_MACHINE_NO_RELA
+   if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_RELOC, 0))
+-    _dl_printf ("\nconflict processing: %s\n",
+-              l->l_name[0] ? l->l_name : rtld_progname);
++    _dl_debug_printf ("\nconflict processing: %s\n",
++                    l->l_name[0] ? l->l_name : rtld_progname);
+   {
+     /* Do the conflict relocation of the object and library GOT and other
diff --git a/src/patches/glibc/glibc-ldconfig-prelink.patch b/src/patches/glibc/glibc-ldconfig-prelink.patch
new file mode 100644 (file)
index 0000000..592362f
--- /dev/null
@@ -0,0 +1,28 @@
+2005-12-27  Jakub Jelinek  <jakub@redhat.com>
+
+       * elf/ldconfig.c (search_dir): Skip prelink temporaries.
+
+--- libc/elf/ldconfig.c        1 Jan 2006 19:15:56 -0000       1.52
++++ libc/elf/ldconfig.c        6 Mar 2006 08:40:11 -0000       1.53
+@@ -693,7 +693,20 @@ search_dir (const struct dir_entry *entr
+ #endif
+             !is_hwcap_platform (direntry->d_name)))
+       continue;
+-      len = strlen (entry->path) + strlen (direntry->d_name);
++      len = strlen (direntry->d_name);
++      /* Skip temporary files created by the prelink program.  Files with
++       names like these are never really DSOs we want to look at.  */
++      if (len >= sizeof (".#prelink#") - 1)
++      {
++        if (strcmp (direntry->d_name + len - sizeof (".#prelink#") + 1,
++                    ".#prelink#") == 0)
++          continue;
++        if (len >= sizeof (".#prelink#.XXXXXX") - 1
++            && memcmp (direntry->d_name + len - sizeof (".#prelink#.XXXXXX")
++                       + 1, ".#prelink#.", sizeof (".#prelink#.") - 1) == 0)
++          continue;
++      }
++      len += strlen (entry->path);
+       if (len > file_name_len)
+       {
+         file_name_len = len + 1;
diff --git a/src/patches/glibc/glibc-lddlibc4.patch b/src/patches/glibc/glibc-lddlibc4.patch
new file mode 100644 (file)
index 0000000..9c228c1
--- /dev/null
@@ -0,0 +1,13 @@
+2005-09-20  Roland McGrath  <roland@redhat.com>
+
+       * sysdeps/unix/sysv/linux/lddlibc4.c (main): Use execv, not execl.
+
+--- libc/sysdeps/unix/sysv/linux/lddlibc4.c    6 Jul 2001 04:56:12 -0000       1.4
++++ libc/sysdeps/unix/sysv/linux/lddlibc4.c    20 Sep 2005 07:46:19 -0000      1.5
+@@ -84,5 +84,5 @@ main (int argc, char *argv[])
+   putenv (buf);
+   /* Now we can execute the binary.  */
+-  return execl (filename, NULL) ? 4 : 0;
++  return execv (filename, &argv[argc]) ? 4 : 0;
+ }
diff --git a/src/patches/glibc/glibc-linuxthreads-atomic_h.patch b/src/patches/glibc/glibc-linuxthreads-atomic_h.patch
new file mode 100644 (file)
index 0000000..abdd241
--- /dev/null
@@ -0,0 +1,66 @@
+2006-02-23  Jakub Jelinek  <jakub@redhat.com>
+
+       * spinlock.h (atomic_increment): Rename to lt_atomic_increment.
+       (atomic_decrement): Rename to lt_atomic_decrement.
+       * pthread.c (__pthread_restart_old, __pthread_suspend_old,
+       __pthread_timedsuspend_old): Adjust callers.
+
+--- libc/linuxthreads/spinlock.h.jj    2003-07-31 21:16:04.000000000 +0200
++++ libc/linuxthreads/spinlock.h       2006-02-23 10:30:04.000000000 +0100
+@@ -172,7 +172,7 @@ static inline int __pthread_alt_trylock 
+ /* Operations on pthread_atomic, which is defined in internals.h */
+-static inline long atomic_increment(struct pthread_atomic *pa)
++static inline long lt_atomic_increment(struct pthread_atomic *pa)
+ {
+     long oldval;
+@@ -184,7 +184,7 @@ static inline long atomic_increment(stru
+ }
+-static inline long atomic_decrement(struct pthread_atomic *pa)
++static inline long lt_atomic_decrement(struct pthread_atomic *pa)
+ {
+     long oldval;
+--- libc/linuxthreads/pthread.c.jj     2005-01-09 21:02:37.000000000 +0100
++++ libc/linuxthreads/pthread.c        2006-02-23 10:30:04.000000000 +0100
+@@ -1231,13 +1231,13 @@ void __pthread_wait_for_restart_signal(p
+ void __pthread_restart_old(pthread_descr th)
+ {
+-  if (atomic_increment(&th->p_resume_count) == -1)
++  if (lt_atomic_increment(&th->p_resume_count) == -1)
+     kill(th->p_pid, __pthread_sig_restart);
+ }
+ void __pthread_suspend_old(pthread_descr self)
+ {
+-  if (atomic_decrement(&self->p_resume_count) <= 0)
++  if (lt_atomic_decrement(&self->p_resume_count) <= 0)
+     __pthread_wait_for_restart_signal(self);
+ }
+@@ -1248,7 +1248,7 @@ __pthread_timedsuspend_old(pthread_descr
+   int was_signalled = 0;
+   sigjmp_buf jmpbuf;
+-  if (atomic_decrement(&self->p_resume_count) == 0) {
++  if (lt_atomic_decrement(&self->p_resume_count) == 0) {
+     /* Set up a longjmp handler for the restart signal, unblock
+        the signal and sleep. */
+@@ -1305,9 +1305,9 @@ __pthread_timedsuspend_old(pthread_descr
+      being delivered. */
+   if (!was_signalled) {
+-    if (atomic_increment(&self->p_resume_count) != -1) {
++    if (lt_atomic_increment(&self->p_resume_count) != -1) {
+       __pthread_wait_for_restart_signal(self);
+-      atomic_decrement(&self->p_resume_count); /* should be zero now! */
++      lt_atomic_decrement(&self->p_resume_count); /* should be zero now! */
+       /* woke spontaneously and consumed restart signal */
+       return 1;
+     }
diff --git a/src/patches/glibc/glibc-loadarchive-leak.patch b/src/patches/glibc/glibc-loadarchive-leak.patch
new file mode 100644 (file)
index 0000000..5b18b98
--- /dev/null
@@ -0,0 +1,20 @@
+2005-09-09  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #1318]
+       * locale/loadarchive.c (_nl_load_locale_from_archive): Free
+       normalized_codeset even if p was already normalized.
+       Reported by Jaroslav Snajdr <jsnajdr@kerio.com>.
+
+--- libc/locale/loadarchive.c  12 Sep 2003 22:26:49 -0000      1.18
++++ libc/locale/loadarchive.c  9 Sep 2005 16:56:52 -0000       1.19
+@@ -185,9 +185,9 @@ _nl_load_locale_from_archive (int catego
+           memcpy (__mempcpy (__mempcpy (newname, name, p - name),
+                              normalized_codeset, normlen),
+                   rest, restlen);
+-          free ((char *) normalized_codeset);
+           name = newname;
+         }
++      free ((char *) normalized_codeset);
+       }
+   }
diff --git a/src/patches/glibc/glibc-localealias-leak.patch b/src/patches/glibc/glibc-localealias-leak.patch
new file mode 100644 (file)
index 0000000..c5a4292
--- /dev/null
@@ -0,0 +1,33 @@
+2005-08-19  Bruno Haible  <bruno@clisp.org>
+
+       * intl/localealias.c (read_alias_file): In case of failure, close the
+       file descriptor and sort the array before returning.
+
+--- libc/intl/localealias.c    4 Sep 2003 08:25:12 -0000       1.42
++++ libc/intl/localealias.c    20 Aug 2005 01:16:17 -0000      1.43
+@@ -295,7 +295,7 @@ read_alias_file (fname, fname_len)
+             if (nmap >= maxmap)
+               if (__builtin_expect (extend_alias_table (), 0))
+-                return added;
++                goto out;
+             alias_len = strlen (alias) + 1;
+             value_len = strlen (value) + 1;
+@@ -308,7 +308,7 @@ read_alias_file (fname, fname_len)
+                                       ? alias_len + value_len : 1024));
+                 char *new_pool = (char *) realloc (string_space, new_size);
+                 if (new_pool == NULL)
+-                  return added;
++                  goto out;
+                 if (__builtin_expect (string_space != new_pool, 0))
+                   {
+@@ -349,6 +349,7 @@ read_alias_file (fname, fname_len)
+       while (strchr (buf, '\n') == NULL);
+     }
++out:
+   /* Should we test for ferror()?  I think we have to silently ignore
+      errors.  --drepper  */
+   fclose (fp);
diff --git a/src/patches/glibc/glibc-madvise-hidden.patch b/src/patches/glibc/glibc-madvise-hidden.patch
new file mode 100644 (file)
index 0000000..94c39fb
--- /dev/null
@@ -0,0 +1,24 @@
+2007-04-19  Ulrich Drepper  <drepper@redhat.com>
+
+       * include/sys/mman.h: Mark madvise hidden.
+       * sysdeps/generic/madvise.c: Add libc_hidden_def.
+
+--- libc/sysdeps/generic/madvise.c     14 Dec 2005 09:36:14 -0000      1.1
++++ libc/sysdeps/generic/madvise.c     19 Apr 2007 17:42:34 -0000      1.2
+@@ -29,5 +29,6 @@ madvise (__ptr_t addr, size_t len, int a
+   __set_errno (ENOSYS);
+   return -1;
+ }
++libc_hidden_def (madvise)
+ stub_warning (madvise)
+ #include <stub-tag.h>
+--- libc/include/sys/mman.h    14 Oct 2005 21:06:10 -0000      1.6
++++ libc/include/sys/mman.h    19 Apr 2007 17:40:54 -0000      1.7
+@@ -12,4 +12,7 @@ extern int __mprotect (void *__addr, siz
+ /* This one is Linux specific.  */
+ extern void *__mremap (void *__addr, size_t __old_len,
+                      size_t __new_len, int __may_move);
++
++libc_hidden_proto (madvise);
++
+ #endif
diff --git a/src/patches/glibc/glibc-nan.patch b/src/patches/glibc/glibc-nan.patch
new file mode 100644 (file)
index 0000000..f02a9e3
--- /dev/null
@@ -0,0 +1,24 @@
+2006-01-04  Joseph S. Myers  <joseph@codesourcery.com>
+
+       * sysdeps/ieee754/bits/nan.h: Fix typo.
+
+--- libc/sysdeps/ieee754/bits/nan.h    16 Apr 2004 22:03:35 -0000      1.9
++++ libc/sysdeps/ieee754/bits/nan.h    4 Jan 2006 06:21:57 -0000       1.10
+@@ -26,13 +26,13 @@
+ #if __GNUC_PREREQ(3,3)
+-# define NAN  (__builtin_nanf(""))
++# define NAN  (__builtin_nanf (""))
+-#elif defined__GNUC__
++#elif defined __GNUC__
+ # define NAN \
+-  (__extension__                                                            \
+-   ((union { unsigned __l __attribute__((__mode__(__SI__))); float __d; })  \
++  (__extension__                                                            \
++   ((union { unsigned __l __attribute__ ((__mode__ (__SI__))); float __d; })  \
+     { __l: 0x7fc00000UL }).__d)
+ #else
diff --git a/src/patches/glibc/glibc-nis+-batch.patch b/src/patches/glibc/glibc-nis+-batch.patch
new file mode 100644 (file)
index 0000000..805d180
--- /dev/null
@@ -0,0 +1,5381 @@
+2006-05-01  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nss_nis/nis-pwd.c (internal_nis_getpwent_r): Don't try to
+       free outkey in error case when batch_read is set.
+
+       * nis/nss_nis/nis-grp.c (internal_nis_getgrent_r): Don't try to
+       free outkey in error case when batch_read is set [Coverity CID 196].
+
+2006-04-30  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nss_nisplus/nisplus-publickey.c (parse_grp_str): PIDLIST is
+       supposed to have NGRPS elements.
+
+       * nis/nss_nisplus/nisplus-parser.c: Minor optimizations and
+       cleanups.  Avoid copying data if it can be used in the old place.
+
+2006-04-29  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nss_nisplus/nisplus-ethers.c: Add missing null pointer check.
+       * nis/nss_nisplus/nisplus-hosts.c: Likewise.
+       * nis/nss_nisplus/nisplus-network.c: Likewise.
+       * nis/nss_nisplus/nisplus-proto.c: Likewise.
+       * nis/nss_nisplus/nisplus-rpc.c: Likewise.
+       * nis/nss_nisplus/nisplus-service.c: Likewise.
+       * nis/nss_nisplus/nisplus-spwd.c: Likewise.
+
+       * nis/nisplus-parser.h (_nss_nisplus_parse_pwent): Add entry
+       parameter.
+       (_nss_nisplus_parse_pwent_chk): New prototype.
+       * nis/nss_nisplus/nisplus-parser.c (_nss_nisplus_parse_pwent):
+       Add entry parameter.  Use it for column value in all accesses.
+       Move checks for well-formed reply to...
+       (_nss_nisplus_parse_pwent_chk): ...here.  New function.
+       * nis/nss_nisplus/nisplus-pwd.c: Support SETENT_BATCH_READ option.
+
+       * nis/nss_nisplus/nisplus-parser.c: Some cleanups.  Remove
+       hidden_def definitions.
+       * nis/nisplus-parser.h: Add parameter names.  Remove hidden_proto
+       definitions.
+
+2006-04-28  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nss_nis/nis-spwd.c (internal_nis_getspent_r): Remove data
+       variable.
+
+       * nis/nss-nis.h: Define response_t and intern_t.  Declare _nis_saveit.
+       * nis/nss_nis/nis-pwd.c: Remove response_t and intern_t definition.
+       (saveit): Renamed to _nis_saveit.  Take parameter which is pointer
+       to the intern_t object.  Change all users.
+       * nis/nss_nis/nis-grp.c: Remove response_t, intern_t, and saveit
+       definition.  Use _nis_saveit instead of saveit.
+       * nis/nss_nis/nis-service.c: Likewise.
+       * nis/nss_nis/nis-initgroups.c: Likewise.
+       (internal_setgrent): Adjust for buffer handling.
+       (internal_getgrent_r): Likewise.
+       * nis/nss_nis/nis-rpc.c: Likewise.
+
+       * nis/nss-default.c (vars): Add SETENT_BATCH_READ.
+       * nis/nss: Document SETENT_BATCH_READ.
+       * nis/libnsl.h: Define NSS_FLAG_SETENT_BATCH_READ.
+       * nis/nss_nis/nis-service.c (saveit): Don't add NUL byte if the
+       string is already NUL terminated.
+       (internal_nis_endservent): No need to return anything.  Change callers.
+       (internal_nis_setservent): One more initialization.
+       * nis/nss_nis/nis-pwd.c: Support SETENT_BATCH_READ option.
+       * nis/nss_nis/nis-grp.c: Likewise.
+
+       * nis/nss-default.c (init): Rewrite parser to get the variables
+       from a table.
+
+       * nis/nss_nis/nis-service.c: Avoid passing pointer to static
+       variable around.  Reduce number of memory allocations by creating
+       list of memory pools.
+
+       * nis/ypclnt.c (__xdr_ypresp_all): Minor optimization in string
+       handling.  Fix typo in comment.
+
+2006-04-23  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nss_nisplus/nisplus-netgrp.c: Cleanups.
+
+2006-04-15  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nss_nisplus/nisplus-publickey.c: Minor cleanups throughout.
+       * nis/nss_nisplus/nisplus-service.c (_nss_nisplus_parse_servent):
+       Significant cleanups.  Correct adjustment for pointer array.
+       * nis/nss_nisplus/nisplus-rpc.c (_nss_nisplus_parse_rpcent):
+       Likewise.
+       * nis/nss_nisplus/nisplus-proto.c (_nss_nisplus_parse_protoent):
+       Likewise.
+       * nis/nss_nisplus/nisplus-network.c (_nss_nisplus_parse_netent):
+       Likewise.
+       * nis/nss_nisplus/nisplus-hosts.c (_nss_nisplus_parse_hostent):
+       Likewise.
+
+2006-04-14  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nss_nisplus/nisplus-ethers.c (_nss_nisplus_parse_etherent):
+       Minor cleanups.  NUL terminate name string.
+
+       * nis/Versions: No need to export _nss_nisplus_parse_grent,
+       _nss_nisplus_parse_pwent, and _nss_nisplus_parse_spent.
+
+       * nis/nss_nisplus/nisplus-alias.c (_nss_nisplus_parse_aliasent):
+       Avoid unnecessary allocation.  Fix adjustment for pointer value.
+
+       * nis/nss_nisplus/nisplus-parser.c: Cleanups, use NIS_RES_*
+       macros.  Avoid unnecessary allocation.
+
+2006-04-13  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/Makefile (libnsl-routimes): Add nss-default.
+       * nis/Versions (libnsl) [GLIBC_PRIVATE]: Export _nsl_default_nss.
+       * nis/nss-nis.c: Move /etc/default/nss handling to...
+       * nis/nss-default.c: ...here.  New file.
+       * nis/libnsl.h: New file.
+       * nis/nss-nis.h: Remove NSS_FLAG_* definitions and _nis_default_nss
+       plus auxilary definitions.
+       * nis/nss_nis/nis-initgroups.c: Use _nsl_default_nss instead of
+       _nis_default_nss.
+       * nis/nss_nis/nis-service.c: Likewise.
+
+2006-04-08  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nss_nis/nis-alias.c: Optimize use of yperr2nss.  Avoid calling
+       it for YPERR_SUCCESS.  Minor cleanups.  Add __builtin_expect.
+       * nis/nss_nis/nis-ethers.c: Likewise.
+       * nis/nss_nis/nis-grp.c: Likewise.
+       * nis/nss_nis/nis-hosts.c: Likewise.
+       * nis/nss_nis/nis-initgroups.c: Likewise.
+       * nis/nss_nis/nis-netgrp.c: Likewise.
+       * nis/nss_nis/nis-network.c: Likewise.
+       * nis/nss_nis/nis-proto.c: Likewise.
+       * nis/nss_nis/nis-publickey.c: Likewise.
+       * nis/nss_nis/nis-pwd.c: Likewise.
+       * nis/nss_nis/nis-rpc.c: Likewise.
+       * nis/nss_nis/nis-service.c: Likewise.
+       * nis/nss_nis/nis-spwd.c: Likewise.
+
+       * nis/nis_ping.c: Remove unnecessary conditionals before
+       nis_freeresult calls.
+       * nis/nis_ismember.c: Likewise.
+
+--- libc/nis/Makefile  8 Sep 2004 15:26:01 -0000       1.31
++++ libc/nis/Makefile  14 Apr 2006 05:45:49 -0000      1.32
+@@ -54,7 +54,7 @@ libnsl-routines = yp_xdr ypclnt ypupdate
+                 nis_print_group_entry nis_domain_of nis_domain_of_r\
+                 nis_modify nis_remove nis_add nis_defaults\
+                 nis_findserv nis_callback nis_clone_dir nis_clone_obj\
+-                nis_clone_res
++                nis_clone_res nss-default
+ libnss_compat-routines        := $(addprefix compat-,grp pwd spwd initgroups)
+ libnss_compat-inhibit-o       = $(filter-out .os,$(object-suffixes))
+--- libc/nis/Versions  1 Feb 2002 23:11:22 -0000       1.7
++++ libc/nis/Versions  14 Apr 2006 21:07:54 -0000      1.9
+@@ -57,6 +57,9 @@ libnsl {
+   GLIBC_2.2 {
+     xdr_ypall;
+   }
++  GLIBC_PRIVATE {
++    _nsl_default_nss;
++  }
+ }
+ libnss_compat {
+@@ -117,8 +120,7 @@ libnss_nisplus {
+     _nss_nisplus_getservbyname_r; _nss_nisplus_getservbynumber_r;
+     _nss_nisplus_getservent_r; _nss_nisplus_getspent_r;
+     _nss_nisplus_getspnam_r; _nss_nisplus_netname2user;
+-    _nss_nisplus_parse_grent; _nss_nisplus_parse_pwent;
+-    _nss_nisplus_parse_spent; _nss_nisplus_setaliasent;
++    _nss_nisplus_setaliasent;
+     _nss_nisplus_setetherent; _nss_nisplus_setgrent; _nss_nisplus_sethostent;
+     _nss_nisplus_setnetent; _nss_nisplus_setnetgrent; _nss_nisplus_setprotoent;
+     _nss_nisplus_setpwent; _nss_nisplus_setrpcent; _nss_nisplus_setservent;
+--- libc/nis/nis_ismember.c    6 Jul 2001 04:55:36 -0000       1.6
++++ libc/nis/nis_ismember.c    8 Apr 2006 20:12:26 -0000       1.7
+@@ -47,8 +47,7 @@ internal_ismember (const_nis_name princi
+   res = nis_lookup (buf, EXPAND_NAME|FOLLOW_LINKS);
+   if (res == NULL || NIS_RES_STATUS (res) != NIS_SUCCESS)
+     {
+-      if (res)
+-      nis_freeresult (res);
++      nis_freeresult (res);
+       return 0;
+     }
+--- libc/nis/nis_ping.c        6 Jul 2001 04:55:36 -0000       1.12
++++ libc/nis/nis_ping.c        8 Apr 2006 20:11:14 -0000       1.13
+@@ -39,8 +39,7 @@ nis_ping (const_nis_name dirname, unsign
+       res = nis_lookup (dirname, MASTER_ONLY);
+       if (res == NULL || NIS_RES_STATUS (res) != NIS_SUCCESS)
+       {
+-        if (res)
+-          nis_freeresult (res);
++        nis_freeresult (res);
+         return;
+       }
+       obj = res->objects.objects_val;
+@@ -51,8 +50,7 @@ nis_ping (const_nis_name dirname, unsign
+   /* Check if obj is really a diryectory object */
+   if (__type_of (obj) != NIS_DIRECTORY_OBJ)
+     {
+-      if (res != NULL)
+-      nis_freeresult (res);
++      nis_freeresult (res);
+       return;
+     }
+@@ -68,6 +66,5 @@ nis_ping (const_nis_name dirname, unsign
+                  NIS_PING, (xdrproc_t) _xdr_ping_args,
+                  (caddr_t) &args, (xdrproc_t) xdr_void,
+                  (caddr_t) NULL, 0, NULL);
+-  if (res)
+-    nis_freeresult (res);
++  nis_freeresult (res);
+ }
+--- libc/nis/nisplus-parser.h  24 Oct 2004 21:22:48 -0000      1.4
++++ libc/nis/nisplus-parser.h  29 Apr 2006 20:16:35 -0000      1.6
+@@ -24,15 +24,16 @@
+ #include <grp.h>
+ #include <shadow.h>
+-extern int _nss_nisplus_parse_pwent (nis_result *, struct passwd *,
+-                                   char *, size_t, int *);
+-extern int _nss_nisplus_parse_grent (nis_result *, u_long, struct group *,
+-                                   char *, size_t, int *);
+-extern int _nss_nisplus_parse_spent (nis_result *, struct spwd *,
+-                                   char *, size_t, int *);
+-
+-libnss_nisplus_hidden_proto (_nss_nisplus_parse_pwent)
+-libnss_nisplus_hidden_proto (_nss_nisplus_parse_grent)
+-libnss_nisplus_hidden_proto (_nss_nisplus_parse_spent)
++extern int _nss_nisplus_parse_pwent (nis_result *result, size_t entry,
++                                   struct passwd *pw, char *buffer,
++                                   size_t buflen, int *errnop);
++extern int _nss_nisplus_parse_pwent_chk (nis_result *result, struct passwd *pw,
++                                       char *buffer, size_t buflen,
++                                       int *errnop);
++extern int _nss_nisplus_parse_grent (nis_result *result, u_long entry,
++                                   struct group *gr, char *buffer,
++                                   size_t buflen, int *errnop);
++extern int _nss_nisplus_parse_spent (nis_result *result, struct spwd *sp,
++                                   char *buffer, size_t buflen, int *errnop);
+ #endif
+--- libc/nis/nss       2 Apr 2004 09:14:48 -0000       1.2
++++ libc/nis/nss       28 Apr 2006 21:02:23 -0000      1.3
+@@ -1,7 +1,7 @@
+ # /etc/default/nss
+ # This file can theoretically contain a bunch of customization variables
+-# for Name Service Switch in the GNU C library.  For now there are only two
+-# variables:
++# for Name Service Switch in the GNU C library.  For now there are only
++# three variables:
+ #
+ # NETID_AUTHORITATIVE
+ #   If set to TRUE, the initgroups() function will accept the information
+@@ -18,3 +18,11 @@
+ #   primary service names and service aliases.  The system administrator
+ #   has to make sure it is correctly generated.
+ #SERVICES_AUTHORITATIVE=TRUE
++#
++# SETENT_BATCH_READ
++#  If set to TRUE, various setXXent() functions will read the entire
++#  database at once and then hand out the requests one by one from
++#  memory with every getXXent() call.  Otherwise each getXXent() call
++#  might result into a network communication with the server to get
++#  the next entry.
++#SETENT_BATCH_READ=TRUE
+--- libc/nis/nss-nis.c 20 Apr 2004 18:52:12 -0000      1.5
++++ libc/nis/nss-nis.c 14 Apr 2006 05:48:48 -0000      1.6
+@@ -16,13 +16,6 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+-#include <ctype.h>
+-#include <stdio.h>
+-#include <stdio_ext.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <rpcsvc/ypclnt.h>
+-
+ #include "nss-nis.h"
+ #include "nsswitch.h"
+@@ -50,81 +43,3 @@ const enum nss_status __yperr2nss_tab[] 
+ };
+ const unsigned int __yperr2nss_count = (sizeof (__yperr2nss_tab)
+                                       / sizeof (__yperr2nss_tab[0]));
+-
+-int _nis_default_nss_flags;
+-
+-static const char default_nss[] = "/etc/default/nss";
+-
+-int
+-_nis_check_default_nss (void)
+-{
+-  FILE *fp = fopen (default_nss, "rc");
+-  int flags = NSS_FLAG_SET;
+-  if (fp != NULL)
+-    {
+-      char *line = NULL;
+-      size_t linelen = 0;
+-
+-      __fsetlocking (fp, FSETLOCKING_BYCALLER);
+-
+-      while (!feof_unlocked (fp))
+-      {
+-        ssize_t n = getline (&line, &linelen, fp);
+-        if (n <= 0)
+-          break;
+-
+-        /* There currently are only two variables we expect, so
+-           simplify the parsing.  Recognize only
+-
+-             NETID_AUTHORITATIVE = TRUE
+-             SERVICES_AUTHORITATIVE = TRUE
+-
+-           with arbitrary white spaces.  */
+-        char *cp = line;
+-        while (isspace (*cp))
+-          ++cp;
+-
+-        /* Recognize comment lines.  */
+-        if (*cp == '#')
+-          continue;
+-
+-        static const char netid_authoritative[] = "NETID_AUTHORITATIVE";
+-        static const char services_authoritative[]
+-          = "SERVICES_AUTHORITATIVE";
+-        size_t flag_len;
+-        if (strncmp (cp, netid_authoritative,
+-                     flag_len = sizeof (netid_authoritative) - 1) != 0
+-            && strncmp (cp, services_authoritative,
+-                        flag_len = sizeof (services_authoritative) - 1)
+-               != 0)
+-          continue;
+-
+-        cp += flag_len;
+-        while (isspace (*cp))
+-          ++cp;
+-        if (*cp++ != '=')
+-          continue;
+-        while (isspace (*cp))
+-          ++cp;
+-
+-        if (strncmp (cp, "TRUE", 4) != 0)
+-          continue;
+-        cp += 4;
+-
+-        while (isspace (*cp))
+-          ++cp;
+-
+-        if (*cp == '\0')
+-          flags |= flag_len == sizeof (netid_authoritative) - 1
+-                   ? NSS_FLAG_NETID_AUTHORITATIVE
+-                   : NSS_FLAG_SERVICES_AUTHORITATIVE;
+-      }
+-
+-      free (line);
+-
+-      fclose (fp);
+-    }
+-
+-  _nis_default_nss_flags = flags;
+-  return flags;
+-}
+--- libc/nis/nss-nis.h 2 Apr 2004 09:15:04 -0000       1.5
++++ libc/nis/nss-nis.h 29 Apr 2006 01:07:41 -0000      1.7
+@@ -36,16 +36,24 @@ yperr2nss (int errval)
+   return __yperr2nss_tab[(unsigned int) errval];
+ }
+-#define NSS_FLAG_SET                  1
+-#define NSS_FLAG_NETID_AUTHORITATIVE  2
+-#define NSS_FLAG_SERVICES_AUTHORITATIVE       4
+-extern int _nis_default_nss_flags attribute_hidden;
+-extern int _nis_check_default_nss (void) attribute_hidden;
+-extern inline __attribute__((always_inline)) int
+-_nis_default_nss (void)
++struct response_t
+ {
+-  return _nis_default_nss_flags ?: _nis_check_default_nss ();
+-}
++  struct response_t *next;
++  size_t size;
++  char mem[0];
++};
++
++typedef struct intern_t
++{
++  struct response_t *start;
++  struct response_t *next;
++  size_t offset;
++} intern_t;
++
++
++extern int _nis_saveit (int instatus, char *inkey, int inkeylen, char *inval,
++                      int invallen, char *indata) attribute_hidden;
++
+ #endif /* nis/nss-nis.h */
+--- libc/nis/ypclnt.c  6 Apr 2006 23:59:35 -0000       1.57
++++ libc/nis/ypclnt.c  28 Apr 2006 16:59:22 -0000      1.58
+@@ -686,10 +686,10 @@ __xdr_ypresp_all (XDR *xdrs, struct ypre
+              if we don't modify the length. So add an extra NUL
+              character to avoid trouble with broken code. */
+           objp->status = YP_TRUE;
+-          memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
+-          key[keylen] = '\0';
+-          memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
+-          val[vallen] = '\0';
++          *((char *) __mempcpy (key, resp.ypresp_all_u.val.key.keydat_val,
++                                keylen)) = '\0';
++          *((char *) __mempcpy (val, resp.ypresp_all_u.val.val.valdat_val,
++                                vallen)) = '\0';
+           xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
+           if ((*objp->foreach) (objp->status, key, keylen,
+                                 val, vallen, objp->data))
+@@ -700,7 +700,7 @@ __xdr_ypresp_all (XDR *xdrs, struct ypre
+         objp->status = resp.ypresp_all_u.val.stat;
+         xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
+         /* Sun says we don't need to make this call, but must return
+-           immediatly. Since Solaris makes this call, we will call
++           immediately. Since Solaris makes this call, we will call
+            the callback function, too. */
+         (*objp->foreach) (objp->status, NULL, 0, NULL, 0, objp->data);
+         return TRUE;
+--- libc/nis/nss_nis/nis-alias.c       6 Apr 2006 22:40:12 -0000       1.17
++++ libc/nis/nss_nis/nis-alias.c       9 Apr 2006 02:08:28 -0000       1.18
+@@ -125,52 +125,53 @@ internal_nis_getaliasent_r (struct alias
+                           size_t buflen, int *errnop)
+ {
+   char *domain;
+-  char *result;
+-  int len;
+-  char *outkey;
+-  int keylen;
+-  char *p;
+-  int parse_res;
+-  if (yp_get_default_domain (&domain))
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+   alias->alias_local = 0;
+   /* Get the next entry until we found a correct one. */
++  int parse_res;
+   do
+     {
+-      enum nss_status retval;
++      char *result;
++      int len;
++      char *outkey;
++      int keylen;
++      int yperr;
+       if (new_start)
+-        retval = yperr2nss (yp_first (domain, "mail.aliases",
+-                                    &outkey, &keylen, &result, &len));
++        yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result,
++                        &len);
+       else
+-        retval = yperr2nss ( yp_next (domain, "mail.aliases", oldkey,
+-                                    oldkeylen, &outkey, &keylen,
+-                                    &result, &len));
+-      if (retval != NSS_STATUS_SUCCESS)
++        yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey,
++                       &keylen, &result, &len);
++
++      if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+       {
++        enum nss_status retval = yperr2nss (yperr);
++
+         if (retval == NSS_STATUS_TRYAGAIN)
+             *errnop = errno;
+           return retval;
+         }
+-      if ((size_t) (len + 1) > buflen)
++      if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+         {
+         free (result);
+           *errnop = ERANGE;
+           return NSS_STATUS_TRYAGAIN;
+         }
+-      p = strncpy (buffer, result, len);
++      char *p = strncpy (buffer, result, len);
+       buffer[len] = '\0';
+       while (isspace (*p))
+         ++p;
+       free (result);
+-      parse_res = _nss_nis_parse_aliasent (outkey, p, alias, buffer, buflen,
+-                                         errnop);
+-      if (parse_res == -1)
++      parse_res = _nss_nis_parse_aliasent (outkey, p, alias, buffer,
++                                         buflen, errnop);
++      if (__builtin_expect (parse_res == -1, 0))
+       {
+         free (outkey);
+         *errnop = ERANGE;
+@@ -216,7 +217,7 @@ _nss_nis_getaliasbyname_r (const char *n
+   char name2[namlen + 1];
+   char *domain;
+-  if (yp_get_default_domain (&domain))
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+   /* Convert name to lowercase.  */
+@@ -227,17 +228,18 @@ _nss_nis_getaliasbyname_r (const char *n
+   char *result;
+   int len;
+-  enum nss_status retval = yperr2nss (yp_match (domain, "mail.aliases", name2,
+-                                              namlen, &result, &len));
++  int yperr = yp_match (domain, "mail.aliases", name2, namlen, &result, &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+       *errnop = errno;
+       return retval;
+     }
+-  if ((size_t) (len + 1) > buflen)
++  if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+     {
+       free (result);
+       *errnop = ERANGE;
+@@ -253,7 +255,7 @@ _nss_nis_getaliasbyname_r (const char *n
+   alias->alias_local = 0;
+   int parse_res = _nss_nis_parse_aliasent (name, p, alias, buffer, buflen,
+                                          errnop);
+-  if (parse_res < 1)
++  if (__builtin_expect (parse_res < 1, 0))
+     {
+       if (parse_res == -1)
+       return NSS_STATUS_TRYAGAIN;
+--- libc/nis/nss_nis/nis-ethers.c      2 Apr 2004 15:09:32 -0000       1.24
++++ libc/nis/nss_nis/nis-ethers.c      9 Apr 2006 02:08:28 -0000       1.25
+@@ -182,45 +182,46 @@ enum nss_status
+ _nss_nis_gethostton_r (const char *name, struct etherent *eth,
+                      char *buffer, size_t buflen, int *errnop)
+ {
+-  struct parser_data *data = (void *) buffer;
+-  enum nss_status retval;
+-  char *domain, *result, *p;
+-  int len, parse_res;
+-
+   if (name == NULL)
+     {
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+     }
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+-  retval = yperr2nss (yp_match (domain, "ethers.byname", name,
+-                              strlen (name), &result, &len));
++  char *result;
++  int len;
++  int yperr = yp_match (domain, "ethers.byname", name, strlen (name), &result,
++                      &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+         *errnop = errno;
+       return retval;
+     }
+-  if ((size_t) (len + 1) > buflen)
++  if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+     {
+       free (result);
+       *errnop = ERANGE;
+       return NSS_STATUS_TRYAGAIN;
+     }
+-  p = strncpy (buffer, result, len);
++  char *p = strncpy (buffer, result, len);
+   buffer[len] = '\0';
+   while (isspace (*p))
+     ++p;
+   free (result);
+-  parse_res = _nss_files_parse_etherent (p, eth, data, buflen, errnop);
+-  if (parse_res < 1)
++  int parse_res = _nss_files_parse_etherent (p, eth, (void *) buffer, buflen,
++                                           errnop);
++  if (__builtin_expect (parse_res < 1, 0))
+     {
+       if (parse_res == -1)
+       return NSS_STATUS_TRYAGAIN;
+@@ -234,54 +235,54 @@ enum nss_status
+ _nss_nis_getntohost_r (const struct ether_addr *addr, struct etherent *eth,
+                      char *buffer, size_t buflen, int *errnop)
+ {
+-  struct parser_data *data = (void *) buffer;
+-  enum nss_status retval;
+-  char *domain, *result, *p;
+-  int len, nlen, parse_res;
+-  char buf[33];
+-
+   if (addr == NULL)
+     {
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+     }
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+-  nlen = sprintf (buf, "%x:%x:%x:%x:%x:%x",
+-                (int) addr->ether_addr_octet[0],
+-                (int) addr->ether_addr_octet[1],
+-                (int) addr->ether_addr_octet[2],
+-                (int) addr->ether_addr_octet[3],
+-                (int) addr->ether_addr_octet[4],
+-                (int) addr->ether_addr_octet[5]);
+-
+-  retval = yperr2nss (yp_match (domain, "ethers.byaddr", buf,
+-                              nlen, &result, &len));
++  char buf[33];
++  int nlen = snprintf (buf, sizeof (buf), "%x:%x:%x:%x:%x:%x",
++                    (int) addr->ether_addr_octet[0],
++                    (int) addr->ether_addr_octet[1],
++                    (int) addr->ether_addr_octet[2],
++                    (int) addr->ether_addr_octet[3],
++                    (int) addr->ether_addr_octet[4],
++                    (int) addr->ether_addr_octet[5]);
++
++  char *result;
++  int len;
++  int yperr = yp_match (domain, "ethers.byaddr", buf, nlen, &result, &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+         *errnop = errno;
+       return retval;
+     }
+-  if ((size_t) (len + 1) > buflen)
++  if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+     {
+       free (result);
+       *errnop = ERANGE;
+       return NSS_STATUS_TRYAGAIN;
+     }
+-  p = strncpy (buffer, result, len);
++  char *p = strncpy (buffer, result, len);
+   buffer[len] = '\0';
+   while (isspace (*p))
+     ++p;
+   free (result);
+-  parse_res = _nss_files_parse_etherent (p, eth, data, buflen, errnop);
+-  if (parse_res < 1)
++  int parse_res = _nss_files_parse_etherent (p, eth, (void *) buffer, buflen,
++                                           errnop);
++  if (__builtin_expect (parse_res < 1, 0))
+     {
+       if (parse_res == -1)
+       return NSS_STATUS_TRYAGAIN;
+--- libc/nis/nss_nis/nis-grp.c 29 Mar 2004 20:02:41 -0000      1.19
++++ libc/nis/nss_nis/nis-grp.c 1 May 2006 22:22:09 -0000       1.23
+@@ -17,20 +17,17 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+-#include <nss.h>
+-/* The following is an ugly trick to avoid a prototype declaration for
+-   _nss_nis_endgrent.  */
+-#define _nss_nis_endgrent _nss_nis_endgrent_XXX
+-#include <grp.h>
+-#undef _nss_nis_endgrent
+ #include <ctype.h>
+ #include <errno.h>
++#include <grp.h>
++#include <nss.h>
+ #include <string.h>
+ #include <bits/libc-lock.h>
+ #include <rpcsvc/yp.h>
+ #include <rpcsvc/ypclnt.h>
+ #include "nss-nis.h"
++#include <libnsl.h>
+ /* Get the declaration of the parser function.  */
+ #define ENTNAME grent
+@@ -44,12 +41,12 @@ __libc_lock_define_initialized (static, 
+ static bool_t new_start = 1;
+ static char *oldkey;
+ static int oldkeylen;
++static intern_t intern;
+-enum nss_status
+-_nss_nis_setgrent (int stayopen)
+-{
+-  __libc_lock_lock (lock);
++static void
++internal_nis_endgrent (void)
++{
+   new_start = 1;
+   if (oldkey != NULL)
+     {
+@@ -58,72 +55,186 @@ _nss_nis_setgrent (int stayopen)
+       oldkeylen = 0;
+     }
++  struct response_t *curr = intern.next;
++
++  while (curr != NULL)
++    {
++      struct response_t *last = curr;
++      curr = curr->next;
++      free (last);
++    }
++
++  intern.next = intern.start = NULL;
++}
++
++
++enum nss_status
++_nss_nis_endgrent (void)
++{
++  __libc_lock_lock (lock);
++
++  internal_nis_endgrent ();
++
+   __libc_lock_unlock (lock);
+   return NSS_STATUS_SUCCESS;
+ }
+-/* Make _nss_nis_endgrent an alias of _nss_nis_setgrent.  We do this
+-   even though the prototypes don't match.  The argument of setgrent
+-   is not used so this makes no difference.  */
+-strong_alias (_nss_nis_setgrent, _nss_nis_endgrent)
++
++
++enum nss_status
++internal_nis_setgrent (void)
++{
++  /* We have to read all the data now.  */
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
++    return NSS_STATUS_UNAVAIL;
++
++  struct ypall_callback ypcb;
++
++  ypcb.foreach = _nis_saveit;
++  ypcb.data = (char *) &intern;
++  enum nss_status status = yperr2nss (yp_all (domain, "group.byname", &ypcb));
++
++
++  /* Mark the last buffer as full.  */
++  if (intern.next != NULL)
++    intern.next->size = intern.offset;
++
++  intern.next = intern.start;
++  intern.offset = 0;
++
++  return status;
++}
++
++
++enum nss_status
++_nss_nis_setgrent (int stayopen)
++{
++  enum nss_status result = NSS_STATUS_SUCCESS;
++
++  __libc_lock_lock (lock);
++
++  internal_nis_endgrent ();
++
++  if (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
++    result = internal_nis_setgrent ();
++
++  __libc_lock_unlock (lock);
++
++  return result;
++}
++
+ static enum nss_status
+ internal_nis_getgrent_r (struct group *grp, char *buffer, size_t buflen,
+                        int *errnop)
+ {
+-  struct parser_data *data = (void *) buffer;
+-  char *domain, *result, *outkey;
+-  int len, keylen, parse_res;
++  /* If we read the entire database at setpwent time we just iterate
++     over the data we have in memory.  */
++  bool batch_read = intern.start != NULL;
+-  if (yp_get_default_domain (&domain))
++  char *domain = NULL;
++  if (!batch_read && __builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+   /* Get the next entry until we found a correct one. */
++  int parse_res;
+   do
+     {
+-      enum nss_status retval;
+-      char *p;
++      char *result;
++      char *outkey;
++      int len;
++      int keylen;
++
++      if (batch_read)
++      {
++        struct response_t *bucket;
++
++      handle_batch_read:
++        bucket = intern.next;
++
++        if (__builtin_expect (intern.offset >= bucket->size, 0))
++          {
++            if (bucket->next == NULL)
++              return NSS_STATUS_NOTFOUND;
++
++            /* We look at all the content in the current bucket.  Go on
++               to the next.  */
++            bucket = intern.next = bucket->next;
++            intern.offset = 0;
++          }
++
++        for (result = &bucket->mem[intern.offset]; isspace (*result);
++             ++result)
++          ++intern.offset;
+-      if (new_start)
+-        retval = yperr2nss (yp_first (domain, "group.byname",
+-                                      &outkey, &keylen, &result, &len));
++        len = strlen (result);
++      }
+       else
+-        retval = yperr2nss ( yp_next (domain, "group.byname",
+-                                      oldkey, oldkeylen,
+-                                      &outkey, &keylen, &result, &len));
++      {
++        int yperr;
+-      if (retval != NSS_STATUS_SUCCESS)
+-        {
+-          if (retval == NSS_STATUS_TRYAGAIN)
+-            *errnop = errno;
+-          return retval;
+-        }
++        if (new_start)
++          {
++            /* Maybe we should read the database in one piece.  */
++            if ((_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
++                && internal_nis_setgrent () == NSS_STATUS_SUCCESS
++                && intern.start != NULL)
++              {
++                batch_read = true;
++                goto handle_batch_read;
++              }
++
++            yperr = yp_first (domain, "group.byname", &outkey, &keylen,
++                              &result, &len);
++          }
++        else
++          yperr = yp_next (domain, "group.byname", oldkey, oldkeylen,
++                           &outkey, &keylen, &result, &len);
++
++        if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
++          {
++            enum nss_status retval = yperr2nss (yperr);
++
++            if (retval == NSS_STATUS_TRYAGAIN)
++              *errnop = errno;
++            return retval;
++          }
++      }
+-      if ((size_t) (len + 1) > buflen)
++      if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+         {
+           free (result);
+           *errnop = ERANGE;
+           return NSS_STATUS_TRYAGAIN;
+         }
+-      p = strncpy (buffer, result, len);
++      char *p = strncpy (buffer, result, len);
+       buffer[len] = '\0';
+       while (isspace (*p))
+         ++p;
+-      free (result);
++      if (!batch_read)
++      free (result);
+-      parse_res = _nss_files_parse_grent (p, grp, data, buflen, errnop);
+-      if (parse_res == -1)
++      parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen,
++                                        errnop);
++      if (__builtin_expect (parse_res == -1, 0))
+       {
+-        free (outkey);
++        if (!batch_read)
++          free (outkey);
+         *errnop = ERANGE;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      free (oldkey);
+-      oldkey = outkey;
+-      oldkeylen = keylen;
+-      new_start = 0;
++      if (batch_read)
++      intern.offset += len + 1;
++      else
++      {
++        free (oldkey);
++        oldkey = outkey;
++        oldkeylen = keylen;
++        new_start = 0;
++      }
+     }
+   while (parse_res < 1);
+@@ -149,45 +260,46 @@ enum nss_status
+ _nss_nis_getgrnam_r (const char *name, struct group *grp,
+                    char *buffer, size_t buflen, int *errnop)
+ {
+-  struct parser_data *data = (void *) buffer;
+-  enum nss_status retval;
+-  char *domain, *result, *p;
+-  int len, parse_res;
+-
+   if (name == NULL)
+     {
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+     }
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+-  retval = yperr2nss (yp_match (domain, "group.byname", name,
+-                              strlen (name), &result, &len));
++  char *result;
++  int len;
++  int yperr = yp_match (domain, "group.byname", name, strlen (name), &result,
++                      &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+         *errnop = errno;
+       return retval;
+     }
+-  if ((size_t) (len + 1) > buflen)
++  if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+     {
+       free (result);
+       *errnop = ERANGE;
+       return NSS_STATUS_TRYAGAIN;
+     }
+-  p = strncpy (buffer, result, len);
++  char *p = strncpy (buffer, result, len);
+   buffer[len] = '\0';
+   while (isspace (*p))
+     ++p;
+   free (result);
+-  parse_res = _nss_files_parse_grent (p, grp, data, buflen, errnop);
+-  if (parse_res < 1)
++  int parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen,
++                                        errnop);
++  if (__builtin_expect  (parse_res < 1, 0))
+     {
+       if (parse_res == -1)
+       return NSS_STATUS_TRYAGAIN;
+@@ -201,42 +313,42 @@ enum nss_status
+ _nss_nis_getgrgid_r (gid_t gid, struct group *grp,
+                    char *buffer, size_t buflen, int *errnop)
+ {
+-  struct parser_data *data = (void *) buffer;
+-  enum nss_status retval;
+-  char *domain, *result, *p;
+-  int len, nlen, parse_res;
+-  char buf[32];
+-
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+-  nlen = sprintf (buf, "%lu", (unsigned long int) gid);
++  char buf[32];
++  int nlen = sprintf (buf, "%lu", (unsigned long int) gid);
+-  retval = yperr2nss (yp_match (domain, "group.bygid", buf,
+-                              nlen, &result, &len));
++  char *result;
++  int len;
++  int yperr = yp_match (domain, "group.bygid", buf, nlen, &result, &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+         *errnop = errno;
+       return retval;
+     }
+-  if ((size_t) (len + 1) > buflen)
++  if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+     {
+       free (result);
+       *errnop = ERANGE;
+       return NSS_STATUS_TRYAGAIN;
+     }
+-  p = strncpy (buffer, result, len);
++  char *p = strncpy (buffer, result, len);
+   buffer[len] = '\0';
+   while (isspace (*p))
+     ++p;
+   free (result);
+-  parse_res = _nss_files_parse_grent (p, grp, data, buflen, errnop);
+-  if (parse_res < 1)
++  int parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen,
++                                        errnop);
++  if (__builtin_expect (parse_res < 1, 0))
+     {
+       if (parse_res == -1)
+       return NSS_STATUS_TRYAGAIN;
+--- libc/nis/nss_nis/nis-hosts.c       16 Mar 2003 03:36:21 -0000      1.25
++++ libc/nis/nss_nis/nis-hosts.c       9 Apr 2006 02:08:28 -0000       1.26
+@@ -131,17 +131,11 @@ internal_nis_gethostent_r (struct hosten
+                          int af, int flags)
+ {
+   char *domain;
+-  char *result;
+-  int len, parse_res;
+-  char *outkey;
+-  int keylen;
+-  struct parser_data *data = (void *) buffer;
+-  size_t linebuflen = buffer + buflen - data->linebuffer;
+-
+-  if (yp_get_default_domain (&domain))
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+-  if (buflen < sizeof *data + 1)
++  struct parser_data *data = (void *) buffer;
++  if (__builtin_expect (buflen < sizeof *data + 1, 0))
+     {
+       *errnop = ERANGE;
+       *h_errnop = NETDB_INTERNAL;
+@@ -149,21 +143,26 @@ internal_nis_gethostent_r (struct hosten
+     }
+   /* Get the next entry until we found a correct one. */
++  const size_t linebuflen = buffer + buflen - data->linebuffer;
++  int parse_res;
+   do
+     {
+-      enum nss_status retval;
+-      char *p;
+-
++      char *result;
++      int len;
++      char *outkey;
++      int keylen;
++      int yperr;
+       if (new_start)
+-        retval = yperr2nss (yp_first (domain, "hosts.byname",
+-                                      &outkey, &keylen, &result, &len));
++        yperr = yp_first (domain, "hosts.byname", &outkey, &keylen, &result,
++                        &len);
+       else
+-        retval = yperr2nss ( yp_next (domain, "hosts.byname",
+-                                      oldkey, oldkeylen,
+-                                      &outkey, &keylen, &result, &len));
++        yperr = yp_next (domain, "hosts.byname", oldkey, oldkeylen, &outkey,
++                       &keylen, &result, &len);
+-      if (retval != NSS_STATUS_SUCCESS)
++      if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+         {
++        enum nss_status retval = yperr2nss (yperr);
++
+         switch (retval)
+           {
+           case NSS_STATUS_TRYAGAIN:
+@@ -180,7 +179,7 @@ internal_nis_gethostent_r (struct hosten
+         return retval;
+       }
+-      if ((size_t) (len + 1) > linebuflen)
++      if (__builtin_expect ((size_t) (len + 1) > linebuflen, 0))
+         {
+           free (result);
+         *h_errnop = NETDB_INTERNAL;
+@@ -188,14 +187,14 @@ internal_nis_gethostent_r (struct hosten
+           return NSS_STATUS_TRYAGAIN;
+         }
+-      p = strncpy (data->linebuffer, result, len);
++      char *p = strncpy (data->linebuffer, result, len);
+       data->linebuffer[len] = '\0';
+       while (isspace (*p))
+       ++p;
+       free (result);
+       parse_res = parse_line (p, host, data, buflen, errnop, af, flags);
+-      if (parse_res == -1)
++      if (__builtin_expect (parse_res == -1, 0))
+       {
+         free (outkey);
+         *h_errnop = NETDB_INTERNAL;
+@@ -235,11 +234,7 @@ internal_gethostbyname2_r (const char *n
+                          char *buffer, size_t buflen, int *errnop,
+                          int *h_errnop, int flags)
+ {
+-  enum nss_status retval;
+-  char *domain, *result, *p;
+-  int len, parse_res;
+   struct parser_data *data = (void *) buffer;
+-  size_t linebuflen = buffer + buflen - data->linebuffer;
+   if (name == NULL)
+     {
+@@ -247,6 +242,7 @@ internal_gethostbyname2_r (const char *n
+       return NSS_STATUS_UNAVAIL;
+     }
++  char *domain;
+   if (yp_get_default_domain (&domain))
+     return NSS_STATUS_UNAVAIL;
+@@ -256,24 +252,24 @@ internal_gethostbyname2_r (const char *n
+       *errnop = ERANGE;
+       return NSS_STATUS_TRYAGAIN;
+     }
+-  else
+-    {
+-      /* Convert name to lowercase.  */
+-      size_t namlen = strlen (name);
+-      char name2[namlen + 1];
+-      size_t i;
+-
+-      for (i = 0; i < namlen; ++i)
+-      name2[i] = tolower (name[i]);
+-      name2[i] = '\0';
+-      retval = yperr2nss (yp_match (domain, "hosts.byname", name2,
+-                                  namlen, &result, &len));
++  /* Convert name to lowercase.  */
++  size_t namlen = strlen (name);
++  char name2[namlen + 1];
++  size_t i;
++
++  for (i = 0; i < namlen; ++i)
++    name2[i] = tolower (name[i]);
++  name2[i] = '\0';
+-    }
++  char *result;
++  int len;
++  int yperr = yp_match (domain, "hosts.byname", name2, namlen, &result, &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+       {
+         *h_errnop = TRY_AGAIN;
+@@ -284,7 +280,8 @@ internal_gethostbyname2_r (const char *n
+       return retval;
+     }
+-  if ((size_t) (len + 1) > linebuflen)
++  const size_t linebuflen = buffer + buflen - data->linebuffer;
++  if (__builtin_expect ((size_t) (len + 1) > linebuflen, 0))
+     {
+       free (result);
+       *h_errnop = NETDB_INTERNAL;
+@@ -292,15 +289,15 @@ internal_gethostbyname2_r (const char *n
+       return NSS_STATUS_TRYAGAIN;
+     }
+-  p = strncpy (data->linebuffer, result, len);
++  char *p = strncpy (data->linebuffer, result, len);
+   data->linebuffer[len] = '\0';
+   while (isspace (*p))
+     ++p;
+   free (result);
+-  parse_res = parse_line (p, host, data, buflen, errnop, af, flags);
++  int parse_res = parse_line (p, host, data, buflen, errnop, af, flags);
+-  if (parse_res < 1 || host->h_addrtype != af)
++  if (__builtin_expect (parse_res < 1 || host->h_addrtype != af, 0))
+     {
+       if (parse_res == -1)
+       {
+@@ -351,42 +348,42 @@ _nss_nis_gethostbyaddr_r (const void *ad
+                         struct hostent *host, char *buffer, size_t buflen,
+                         int *errnop, int *h_errnop)
+ {
+-  enum nss_status retval;
+-  char *domain, *result, *p;
+-  int len, parse_res;
+-  char *buf;
+-  struct parser_data *data = (void *) buffer;
+-  size_t linebuflen = buffer + buflen - data->linebuffer;
+-
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+-  if (buflen < sizeof *data + 1)
++  struct parser_data *data = (void *) buffer;
++  if (__builtin_expect (buflen < sizeof *data + 1, 0))
+     {
+       *errnop = ERANGE;
+       *h_errnop = NETDB_INTERNAL;
+       return NSS_STATUS_TRYAGAIN;
+     }
+-  buf = inet_ntoa (*(const struct in_addr *) addr);
++  char *buf = inet_ntoa (*(const struct in_addr *) addr);
+-  retval = yperr2nss (yp_match (domain, "hosts.byaddr", buf,
+-                                strlen (buf), &result, &len));
++  char *result;
++  int len;
++  int yperr = yp_match (domain, "hosts.byaddr", buf, strlen (buf), &result,
++                      &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+       {
+         *h_errnop = TRY_AGAIN;
+         *errnop = errno;
+       }
+-      if (retval == NSS_STATUS_NOTFOUND)
++      else if (retval == NSS_STATUS_NOTFOUND)
+       *h_errnop = HOST_NOT_FOUND;
+       return retval;
+     }
+-  if ((size_t) (len + 1) > linebuflen)
++  const size_t linebuflen = buffer + buflen - data->linebuffer;
++  if (__builtin_expect ((size_t) (len + 1) > linebuflen, 0))
+     {
+       free (result);
+       *errnop = ERANGE;
+@@ -394,15 +391,16 @@ _nss_nis_gethostbyaddr_r (const void *ad
+       return NSS_STATUS_TRYAGAIN;
+     }
+-  p = strncpy (data->linebuffer, result, len);
++  char *p = strncpy (data->linebuffer, result, len);
+   data->linebuffer[len] = '\0';
+   while (isspace (*p))
+     ++p;
+   free (result);
+-  parse_res = parse_line (p, host, data, buflen, errnop, af,
+-                        ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0));
+-  if (parse_res < 1)
++  int parse_res = parse_line (p, host, data, buflen, errnop, af,
++                            ((_res.options & RES_USE_INET6)
++                             ? AI_V4MAPPED : 0));
++  if (__builtin_expect (parse_res < 1, 0))
+     {
+       if (parse_res == -1)
+       {
+--- libc/nis/nss_nis/nis-initgroups.c  2 Apr 2004 15:09:32 -0000       1.14
++++ libc/nis/nss_nis/nis-initgroups.c  29 Apr 2006 01:12:53 -0000      1.17
+@@ -30,6 +30,7 @@
+ #include <sys/param.h>
+ #include "nss-nis.h"
++#include <libnsl.h>
+ /* Get the declaration of the parser function.  */
+ #define ENTNAME grent
+@@ -37,47 +38,6 @@
+ #define EXTERN_PARSER
+ #include <nss/nss_files/files-parse.c>
+-struct response_t
+-{
+-  struct response_t *next;
+-  char val[0];
+-};
+-
+-struct intern_t
+-{
+-  struct response_t *start;
+-  struct response_t *next;
+-};
+-typedef struct intern_t intern_t;
+-
+-static int
+-saveit (int instatus, char *inkey, int inkeylen, char *inval,
+-        int invallen, char *indata)
+-{
+-  intern_t *intern = (intern_t *) indata;
+-
+-  if (instatus != YP_TRUE)
+-    return 1;
+-
+-  if (inkey && inkeylen > 0 && inval && invallen > 0)
+-    {
+-      struct response_t *newp = malloc (sizeof (struct response_t)
+-                                      + invallen + 1);
+-      if (newp == NULL)
+-      return 1; /* We have no error code for out of memory */
+-
+-      if (intern->start == NULL)
+-      intern->start = newp;
+-      else
+-      intern->next->next = newp;
+-      intern->next = newp;
+-
+-      newp->next = NULL;
+-      *((char *) mempcpy (newp->val, inval, invallen)) = '\0';
+-    }
+-
+-  return 0;
+-}
+ static enum nss_status
+ internal_setgrent (char *domainname, intern_t *intern)
+@@ -85,41 +45,72 @@ internal_setgrent (char *domainname, int
+   struct ypall_callback ypcb;
+   enum nss_status status;
+-  intern->start = NULL;
+-
+-  ypcb.foreach = saveit;
++  ypcb.foreach = _nis_saveit;
+   ypcb.data = (char *) intern;
+   status = yperr2nss (yp_all (domainname, "group.byname", &ypcb));
++
++  /* Mark the last buffer as full.  */
++  if (intern->next != NULL)
++    intern->next->size = intern->offset;
++
+   intern->next = intern->start;
++  intern->offset = 0;
+   return status;
+ }
++
+ static enum nss_status
+ internal_getgrent_r (struct group *grp, char *buffer, size_t buflen,
+                    int *errnop, intern_t *intern)
+ {
+-  struct parser_data *data = (void *) buffer;
+-  int parse_res;
+-  char *p;
+-
+   if (intern->start == NULL)
+     return NSS_STATUS_NOTFOUND;
+   /* Get the next entry until we found a correct one. */
++  int parse_res;
+   do
+     {
+-      if (intern->next == NULL)
+-      return NSS_STATUS_NOTFOUND;
++      struct response_t *bucket = intern->next;
++
++      if (__builtin_expect (intern->offset >= bucket->size, 0))
++      {
++        if (bucket->next == NULL)
++          return NSS_STATUS_NOTFOUND;
++
++        /* We look at all the content in the current bucket.  Go on
++           to the next.  */
++        bucket = intern->next = bucket->next;
++        intern->offset = 0;
++      }
+-      p = strncpy (buffer, intern->next->val, buflen);
+-      while (isspace (*p))
+-        ++p;
++      char *p;
++      for (p = &bucket->mem[intern->offset]; isspace (*p); ++p)
++        ++intern->offset;
+-      parse_res = _nss_files_parse_grent (p, grp, data, buflen, errnop);
+-      if (parse_res == -1)
++      size_t len = strlen (p) + 1;
++      if (__builtin_expect (len > buflen, 0))
++      {
++        *errnop = ERANGE;
++        return NSS_STATUS_TRYAGAIN;
++      }
++
++      /* We unfortunately have to copy the data in the user-provided
++       buffer because that buffer might be around for a very long
++       time and the servent structure must remain valid.  If we would
++       rely on the BUCKET memory the next 'setservent' or 'endservent'
++       call would destroy it.
++
++       The important thing is that it is a single NUL-terminated
++       string.  This is what the parsing routine expects.  */
++      p = memcpy (buffer, &bucket->mem[intern->offset], len);
++
++      parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen,
++                                        errnop);
++      if (__builtin_expect (parse_res == -1, 0))
+         return NSS_STATUS_TRYAGAIN;
+-      intern->next = intern->next->next;
++
++      intern->offset += len;
+     }
+   while (!parse_res);
+@@ -166,13 +157,12 @@ initgroups_netid (uid_t uid, gid_t group
+   ssize_t keylen = snprintf (key, sizeof (key), "unix.%lu@%s",
+                            (unsigned long int) uid, domainname);
+-  enum nss_status retval;
+   char *result;
+   int reslen;
+-  retval = yperr2nss (yp_match (domainname, "netid.byname", key, keylen,
+-                              &result, &reslen));
+-  if (retval != NSS_STATUS_SUCCESS)
+-    return retval;
++  int yperr = yp_match (domainname, "netid.byname", key, keylen, &result,
++                      &reslen);
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
++    return yperr2nss (yperr);
+   /* Parse the result: following the colon is a comma separated list of
+      group IDs.  */
+@@ -207,7 +197,6 @@ initgroups_netid (uid_t uid, gid_t group
+       if (*start == *size)
+       {
+         /* Need a bigger buffer.  */
+-        gid_t *newgroups;
+         long int newsize;
+         if (limit > 0 && *size == limit)
+@@ -219,7 +208,7 @@ initgroups_netid (uid_t uid, gid_t group
+         else
+           newsize = MIN (limit, 2 * *size);
+-        newgroups = realloc (groups, newsize * sizeof (*groups));
++        gid_t *newgroups = realloc (groups, newsize * sizeof (*groups));
+         if (newgroups == NULL)
+           goto errout;
+         *groupsp = groups = newgroups;
+@@ -247,7 +236,7 @@ _nss_nis_initgroups_dyn (const char *use
+     return NSS_STATUS_UNAVAIL;
+   /* Check whether we are supposed to use the netid.byname map.  */
+-  if (_nis_default_nss () & NSS_FLAG_NETID_AUTHORITATIVE)
++  if (_nsl_default_nss () & NSS_FLAG_NETID_AUTHORITATIVE)
+     {
+       /* We need the user ID.  */
+       uid_t uid;
+@@ -262,7 +251,7 @@ _nss_nis_initgroups_dyn (const char *use
+   size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
+   char *tmpbuf;
+   enum nss_status status;
+-  intern_t intern = { NULL, NULL };
++  intern_t intern = { NULL, NULL, 0 };
+   gid_t *groups = *groupsp;
+   status = internal_setgrent (domainname, &intern);
+--- libc/nis/nss_nis/nis-netgrp.c      10 Sep 2005 03:19:20 -0000      1.14
++++ libc/nis/nss_nis/nis-netgrp.c      9 Apr 2006 02:08:28 -0000       1.15
+@@ -47,24 +47,25 @@ internal_nis_endnetgrent (struct __netgr
+   netgrp->cursor = NULL;
+ }
++
+ enum nss_status
+ _nss_nis_setnetgrent (const char *group, struct __netgrent *netgrp)
+ {
+-  char *domain;
+   int len;
+   enum nss_status status;
+   status = NSS_STATUS_SUCCESS;
+-  if (group == NULL || group[0] == '\0')
++  if (__builtin_expect (group == NULL || group[0] == '\0', 0))
+     return NSS_STATUS_UNAVAIL;
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+   status = yperr2nss (yp_match (domain, "netgroup", group, strlen (group),
+                               &netgrp->data, &len));
+-  if (status == NSS_STATUS_SUCCESS)
++  if (__builtin_expect (status == NSS_STATUS_SUCCESS, 1))
+     {
+       /* Our implementation of yp_match already allocates a buffer
+        which is one byte larger than the value in LEN specifies
+@@ -90,6 +91,7 @@ _nss_nis_endnetgrent (struct __netgrent 
+   return NSS_STATUS_SUCCESS;
+ }
++
+ enum nss_status
+ _nss_nis_getnetgrent_r (struct __netgrent *result, char *buffer, size_t buflen,
+                       int *errnop)
+--- libc/nis/nss_nis/nis-network.c     16 Mar 2003 03:36:21 -0000      1.19
++++ libc/nis/nss_nis/nis-network.c     9 Apr 2006 02:08:28 -0000       1.20
+@@ -73,28 +73,32 @@ internal_nis_getnetent_r (struct netent 
+                         int *errnop, int *herrnop)
+ {
+   struct parser_data *data = (void *) buffer;
+-  char *domain, *result, *outkey;
+-  int len, keylen, parse_res;
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+   /* Get the next entry until we found a correct one. */
++  int parse_res;
+   do
+     {
+-      enum nss_status retval;
+-      char *p;
++      char *result;
++      char *outkey;
++      int len;
++      int keylen;
++      int yperr;
+       if (new_start)
+-        retval = yperr2nss (yp_first (domain, "networks.byname",
+-                                      &outkey, &keylen, &result, &len));
++        yperr = yp_first (domain, "networks.byname", &outkey, &keylen, &result,
++                        &len);
+       else
+-        retval = yperr2nss ( yp_next (domain, "networks.byname",
+-                                      oldkey, oldkeylen,
+-                                      &outkey, &keylen, &result, &len));
++        yperr = yp_next (domain, "networks.byname", oldkey, oldkeylen, &outkey,
++                       &keylen, &result, &len);
+-      if (retval != NSS_STATUS_SUCCESS)
++      if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+         {
++        enum nss_status retval = yperr2nss (yperr);
++
+           if (retval == NSS_STATUS_TRYAGAIN)
+           {
+             *herrnop = NETDB_INTERNAL;
+@@ -103,7 +107,7 @@ internal_nis_getnetent_r (struct netent 
+           return retval;
+         }
+-      if ((size_t) (len + 1) > buflen)
++      if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+         {
+           free (result);
+         *errnop = ERANGE;
+@@ -111,14 +115,14 @@ internal_nis_getnetent_r (struct netent 
+           return NSS_STATUS_TRYAGAIN;
+         }
+-      p = strncpy (buffer, result, len);
++      char *p = strncpy (buffer, result, len);
+       buffer[len] = '\0';
+       while (isspace (*p))
+         ++p;
+       free (result);
+       parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop);
+-      if (parse_res == -1)
++      if (__builtin_expect (parse_res == -1, 0))
+       {
+         free (outkey);
+         *herrnop = NETDB_INTERNAL;
+@@ -155,11 +159,6 @@ enum nss_status
+ _nss_nis_getnetbyname_r (const char *name, struct netent *net, char *buffer,
+                        size_t buflen, int *errnop, int *herrnop)
+ {
+-  enum nss_status retval;
+-  struct parser_data *data = (void *) buffer;
+-  char *domain, *result, *p;
+-  int len, parse_res;
+-
+   if (name == NULL)
+     {
+       *errnop = EINVAL;
+@@ -167,33 +166,36 @@ _nss_nis_getnetbyname_r (const char *nam
+       return NSS_STATUS_UNAVAIL;
+     }
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
++  struct parser_data *data = (void *) buffer;
+   if (buflen < sizeof *data + 1)
+     {
+       *herrnop = NETDB_INTERNAL;
+       *errnop = ERANGE;
+       return NSS_STATUS_TRYAGAIN;
+     }
+-  else
+-    {
+-      /* Convert name to lowercase.  */
+-      size_t namlen = strlen (name);
+-      char name2[namlen + 1];
+-      size_t i;
+-
+-      for (i = 0; i < namlen; ++i)
+-      name2[i] = _tolower (name[i]);
+-      name2[i] = '\0';
+-      retval = yperr2nss (yp_match (domain, "networks.byname", name2,
+-                                  namlen, &result, &len));
+-    }
++  /* Convert name to lowercase.  */
++  size_t namlen = strlen (name);
++  char name2[namlen + 1];
++  size_t i;
++
++  for (i = 0; i < namlen; ++i)
++    name2[i] = _tolower (name[i]);
++  name2[i] = '\0';
++  char *result;
++  int len;
++  int yperr = yp_match (domain, "networks.byname", name2, namlen, &result,
++                      &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+       {
+         *errnop = errno;
+@@ -202,7 +204,7 @@ _nss_nis_getnetbyname_r (const char *nam
+       return retval;
+     }
+-  if ((size_t) (len + 1) > buflen)
++  if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+     {
+       free (result);
+       *errnop = ERANGE;
+@@ -210,15 +212,15 @@ _nss_nis_getnetbyname_r (const char *nam
+       return NSS_STATUS_TRYAGAIN;
+     }
+-  p = strncpy (buffer, result, len);
++  char *p = strncpy (buffer, result, len);
+   buffer[len] = '\0';
+   while (isspace (*p))
+     ++p;
+   free (result);
+-  parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop);
++  int parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop);
+-  if (parse_res < 1)
++  if (__builtin_expect (parse_res < 1, 0))
+     {
+       *herrnop = NETDB_INTERNAL;
+       if (parse_res == -1)
+@@ -235,32 +237,26 @@ _nss_nis_getnetbyaddr_r (uint32_t addr, 
+                        char *buffer, size_t buflen, int *errnop,
+                        int *herrnop)
+ {
+-  struct parser_data *data = (void *) buffer;
+   char *domain;
+-  char *result;
+-  int len;
+-  char buf[256];
+-  int blen;
+-  struct in_addr in;
+-  char *p;
+-
+-  if (yp_get_default_domain (&domain))
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+-  in = inet_makeaddr (addr, 0);
+-  strcpy (buf, inet_ntoa (in));
+-  blen = strlen (buf);
++  struct in_addr in = inet_makeaddr (addr, 0);
++  char *buf = inet_ntoa (in);
++  size_t blen = strlen (buf);
+   while (1)
+     {
+-      enum nss_status retval;
+-      int parse_res;
++      char *result;
++      int len;
+-      retval = yperr2nss (yp_match (domain, "networks.byaddr", buf,
+-                                  strlen (buf), &result, &len));
++      int yperr = yp_match (domain, "networks.byaddr", buf, blen, &result,
++                          &len);
+-      if (retval != NSS_STATUS_SUCCESS)
++      if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+         {
++          enum nss_status retval = yperr2nss (yperr);
++
+           if (retval == NSS_STATUS_NOTFOUND)
+             {
+               if (buf[blen - 2] == '.' && buf[blen - 1] == '0')
+@@ -282,7 +278,7 @@ _nss_nis_getnetbyaddr_r (uint32_t addr, 
+             }
+         }
+-      if ((size_t) (len + 1) > buflen)
++      if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+       {
+         free (result);
+         *errnop = ERANGE;
+@@ -290,15 +286,16 @@ _nss_nis_getnetbyaddr_r (uint32_t addr, 
+         return NSS_STATUS_TRYAGAIN;
+       }
+-        p = strncpy (buffer, result, len);
++        char *p = strncpy (buffer, result, len);
+       buffer[len] = '\0';
+       while (isspace (*p))
+         ++p;
+       free (result);
+-      parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop);
++      int parse_res = _nss_files_parse_netent (p, net, (void *) buffer,
++                                               buflen, errnop);
+-      if (parse_res < 1)
++      if (__builtin_expect (parse_res < 1, 0))
+         {
+           *herrnop = NETDB_INTERNAL;
+           if (parse_res == -1)
+--- libc/nis/nss_nis/nis-proto.c       2 Apr 2004 15:09:32 -0000       1.21
++++ libc/nis/nss_nis/nis-proto.c       9 Apr 2006 02:08:28 -0000       1.22
+@@ -179,45 +179,46 @@ enum nss_status
+ _nss_nis_getprotobyname_r (const char *name, struct protoent *proto,
+                          char *buffer, size_t buflen, int *errnop)
+ {
+-  struct parser_data *data = (void *) buffer;
+-  enum nss_status retval;
+-  char *domain, *result, *p;
+-  int len, parse_res;
+-
+   if (name == NULL)
+     {
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+     }
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+-  retval = yperr2nss (yp_match (domain, "protocols.byname", name,
+-                                strlen (name), &result, &len));
++  char *result;
++  int len;
++  int yperr = yp_match (domain, "protocols.byname", name, strlen (name),
++                      &result, &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+       *errnop = errno;
+       return retval;
+     }
+-  if ((size_t) (len + 1) > buflen)
++  if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+     {
+       free (result);
+       *errnop = ERANGE;
+       return NSS_STATUS_TRYAGAIN;
+     }
+-  p = strncpy (buffer, result, len);
++  char *p = strncpy (buffer, result, len);
+   buffer[len] = '\0';
+   while (isspace (*p))
+     ++p;
+   free (result);
+-  parse_res = _nss_files_parse_protoent (p, proto, data, buflen, errnop);
+-  if (parse_res < 1)
++  int parse_res = _nss_files_parse_protoent (p, proto, (void *) buffer, buflen,
++                                           errnop);
++  if (__builtin_expect (parse_res < 1, 0))
+     {
+       if (parse_res == -1)
+       return NSS_STATUS_TRYAGAIN;
+@@ -231,42 +232,43 @@ enum nss_status
+ _nss_nis_getprotobynumber_r (int number, struct protoent *proto,
+                            char *buffer, size_t buflen, int *errnop)
+ {
+-  struct parser_data *data = (void *) buffer;
+-  enum nss_status retval;
+-  char *domain, *result, *p;
+-  int len, nlen, parse_res;
+-  char buf[32];
+-
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+-  nlen = sprintf (buf, "%d", number);
++  char buf[32];
++  int nlen = snprintf (buf, sizeof (buf), "%d", number);
+-  retval = yperr2nss (yp_match (domain, "protocols.bynumber", buf,
+-                                nlen, &result, &len));
++  char *result;
++  int len;
++  int yperr = yp_match (domain, "protocols.bynumber", buf, nlen, &result,
++                      &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+       *errnop = errno;
+       return retval;
+     }
+-  if ((size_t) (len + 1) > buflen)
++  if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+     {
+       free (result);
+       *errnop = ERANGE;
+       return NSS_STATUS_TRYAGAIN;
+     }
+-  p = strncpy (buffer, result, len);
++  char *p = strncpy (buffer, result, len);
+   buffer[len] = '\0';
+   while (isspace (*p))
+     ++p;
+   free (result);
+-  parse_res = _nss_files_parse_protoent (p, proto, data, buflen, errnop);
+-  if (parse_res < 1)
++  int parse_res = _nss_files_parse_protoent (p, proto, (void *) buffer, buflen,
++                                           errnop);
++  if (__builtin_expect (parse_res < 1, 0))
+     {
+       if (parse_res == -1)
+       return NSS_STATUS_TRYAGAIN;
+--- libc/nis/nss_nis/nis-publickey.c   6 Apr 2006 23:22:40 -0000       1.16
++++ libc/nis/nss_nis/nis-publickey.c   9 Apr 2006 02:08:28 -0000       1.17
+@@ -36,10 +36,6 @@ extern int xdecrypt (char *, char *);
+ enum nss_status
+ _nss_nis_getpublickey (const char *netname, char *pkey, int *errnop)
+ {
+-  enum nss_status retval;
+-  char *domain, *result;
+-  int len;
+-
+   pkey[0] = 0;
+   if (netname == NULL)
+@@ -48,19 +44,23 @@ _nss_nis_getpublickey (const char *netna
+       return NSS_STATUS_UNAVAIL;
+     }
+-  domain = strchr (netname, '@');
+-  if (!domain)
++  char *domain = strchr (netname, '@');
++  if (domain == NULL)
+     {
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+     }
+   ++domain;
+-  retval = yperr2nss (yp_match (domain, "publickey.byname", netname,
+-                              strlen (netname), &result, &len));
++  char *result;
++  int len;
++  int yperr = yp_match (domain, "publickey.byname", netname, strlen (netname),
++                      &result, &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+       *errnop = errno;
+       return retval;
+@@ -82,11 +82,6 @@ enum nss_status
+ _nss_nis_getsecretkey (const char *netname, char *skey, char *passwd,
+                      int *errnop)
+ {
+-  enum nss_status retval;
+-  char buf[2 * (HEXKEYBYTES + 1)];
+-  char *domain, *result;
+-  int len;
+-
+   skey[0] = 0;
+   if (netname == NULL || passwd == NULL)
+@@ -95,19 +90,23 @@ _nss_nis_getsecretkey (const char *netna
+       return NSS_STATUS_UNAVAIL;
+     }
+-  domain = strchr (netname, '@');
+-  if (!domain)
++  char *domain = strchr (netname, '@');
++  if (domain == NULL)
+     {
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+     }
+   ++domain;
+-  retval = yperr2nss (yp_match (domain, "publickey.byname", netname,
+-                              strlen (netname), &result, &len));
++  char *result;
++  int len;
++  int yperr = yp_match (domain, "publickey.byname", netname, strlen (netname),
++                      &result, &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+       *errnop = errno;
+       return retval;
+@@ -118,6 +117,8 @@ _nss_nis_getsecretkey (const char *netna
+       char *p = strchr (result, ':');
+       if (p != NULL)
+       {
++        char buf[2 * (HEXKEYBYTES + 1)];
++
+         ++p;
+         strncpy (buf, p, 2 * (HEXKEYBYTES + 1));
+         buf[2 * HEXKEYBYTES + 1] = '\0';
+@@ -195,13 +196,8 @@ enum nss_status
+ _nss_nis_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp,
+                      gid_t *gidp, int *gidlenp, gid_t *gidlist, int *errnop)
+ {
+-  char *domain;
+-  int yperr;
+-  char *lookup;
+-  int len;
+-
+-  domain = strchr (netname, '@');
+-  if (!domain)
++  char *domain = strchr (netname, '@');
++  if (domain == NULL)
+     {
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+@@ -209,9 +205,10 @@ _nss_nis_netname2user (char netname[MAXN
+   /* Point past the '@' character */
+   ++domain;
+-  lookup = NULL;
+-  yperr = yp_match (domain, "netid.byname", netname, strlen (netname),
+-                  &lookup, &len);
++  char *lookup = NULL;
++  int len;
++  int yperr = yp_match (domain, "netid.byname", netname, strlen (netname),
++                      &lookup, &len);
+   switch (yperr)
+     {
+     case YPERR_SUCCESS:
+@@ -224,17 +221,15 @@ _nss_nis_netname2user (char netname[MAXN
+       return NSS_STATUS_UNAVAIL;
+     }
+-  if (lookup)
+-    {
+-      enum nss_status err;
+-
+-      lookup[len] = '\0';
+-      err = parse_netid_str (lookup, uidp, gidp, gidlenp, gidlist);
+-      free (lookup);
+-      return err;
+-    }
+-  else
++  if (lookup == NULL)
+     return NSS_STATUS_NOTFOUND;
+-  return NSS_STATUS_SUCCESS;
++
++  lookup[len] = '\0';
++
++  enum nss_status err = parse_netid_str (lookup, uidp, gidp, gidlenp, gidlist);
++
++  free (lookup);
++
++  return err;
+ }
+--- libc/nis/nss_nis/nis-pwd.c 19 Jan 2003 19:09:10 -0000      1.18
++++ libc/nis/nss_nis/nis-pwd.c 1 May 2006 22:31:15 -0000       1.21
+@@ -17,20 +17,18 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+-#include <nss.h>
+-/* The following is an ugly trick to avoid a prototype declaration for
+-   _nss_nis_endpwent.  */
+-#define _nss_nis_endpwent _nss_nis_endpwent_XXX
+-#include <pwd.h>
+-#undef _nss_nis_endpwent
++#include <assert.h>
+ #include <ctype.h>
+ #include <errno.h>
++#include <nss.h>
++#include <pwd.h>
+ #include <string.h>
+ #include <bits/libc-lock.h>
+ #include <rpcsvc/yp.h>
+ #include <rpcsvc/ypclnt.h>
+ #include "nss-nis.h"
++#include <libnsl.h>
+ /* Get the declaration of the parser function.  */
+ #define ENTNAME pwent
+@@ -44,12 +42,72 @@ __libc_lock_define_initialized (static, 
+ static bool_t new_start = 1;
+ static char *oldkey;
+ static int oldkeylen;
++static intern_t intern;
+-enum nss_status
+-_nss_nis_setpwent (int stayopen)
++
++int
++_nis_saveit (int instatus, char *inkey, int inkeylen, char *inval,
++           int invallen, char *indata)
+ {
+-  __libc_lock_lock (lock);
++  intern_t *intern = (intern_t *) indata;
++
++  if (instatus != YP_TRUE)
++    return 1;
++
++  if (inkey && inkeylen > 0 && inval && invallen > 0)
++    {
++      struct response_t *bucket = intern->next;
++      if (__builtin_expect (bucket == NULL, 0))
++      {
++#define MINSIZE 4096 - 4 * sizeof (void *)
++        const size_t minsize = MAX (MINSIZE, 2 * (invallen + 1));
++        bucket = malloc (sizeof (struct response_t) + minsize);
++        if (bucket == NULL)
++          /* We have no error code for out of memory.  */
++          return 1;
++
++        bucket->next = NULL;
++        bucket->size = minsize;
++        intern->start = intern->next = bucket;
++        intern->offset = 0;
++      }
++      else if (__builtin_expect (invallen + 1 > bucket->size - intern->offset,
++                               0))
++      {
++        /* We need a new (larger) buffer.  */
++        const size_t newsize = 2 * MAX (bucket->size, invallen + 1);
++        struct response_t *newp = malloc (sizeof (struct response_t)
++                                          + newsize);
++        if (newp == NULL)
++          /* We have no error code for out of memory.  */
++          return 1;
++
++        /* Mark the old bucket as full.  */
++        bucket->size = intern->offset;
++
++        newp->next = NULL;
++        newp->size = newsize;
++        bucket = intern->next = bucket->next = newp;
++        intern->offset = 0;
++      }
++
++      char *p = mempcpy (&bucket->mem[intern->offset], inval, invallen);
++      if (__builtin_expect (p[-1] != '\0', 0))
++      {
++        *p = '\0';
++        ++invallen;
++      }
++      intern->offset += invallen;
++    }
++
++  return 0;
++}
++
++
++static void
++internal_nis_endpwent (void)
++{
+   new_start = 1;
+   if (oldkey != NULL)
+     {
+@@ -58,52 +116,159 @@ _nss_nis_setpwent (int stayopen)
+       oldkeylen = 0;
+     }
++  struct response_t *curr = intern.next;
++
++  while (curr != NULL)
++    {
++      struct response_t *last = curr;
++      curr = curr->next;
++      free (last);
++    }
++
++  intern.next = intern.start = NULL;
++}
++
++
++enum nss_status
++_nss_nis_endpwent (void)
++{
++  __libc_lock_lock (lock);
++
++  internal_nis_endpwent ();
++
+   __libc_lock_unlock (lock);
+   return NSS_STATUS_SUCCESS;
+ }
+-/* Make _nss_nis_endpwent an alias of _nss_nis_setpwent.  We do this
+-   even though the prototypes don't match.  The argument of setpwent
+-   is not used so this makes no difference.  */
+-strong_alias (_nss_nis_setpwent, _nss_nis_endpwent)
++
++
++enum nss_status
++internal_nis_setpwent (void)
++{
++  /* We have to read all the data now.  */
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
++    return NSS_STATUS_UNAVAIL;
++
++  struct ypall_callback ypcb;
++
++  ypcb.foreach = _nis_saveit;
++  ypcb.data = (char *) &intern;
++  enum nss_status status = yperr2nss (yp_all (domain, "passwd.byname", &ypcb));
++
++
++  /* Mark the last buffer as full.  */
++  if (intern.next != NULL)
++    intern.next->size = intern.offset;
++
++  intern.next = intern.start;
++  intern.offset = 0;
++
++  return status;
++}
++
++
++enum nss_status
++_nss_nis_setpwent (int stayopen)
++{
++  enum nss_status result = NSS_STATUS_SUCCESS;
++
++  __libc_lock_lock (lock);
++
++  internal_nis_endpwent ();
++
++  if (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
++    result = internal_nis_setpwent ();
++
++  __libc_lock_unlock (lock);
++
++  return result;
++}
++
+ static enum nss_status
+ internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen,
+                        int *errnop)
+ {
+-  struct parser_data *data = (void *) buffer;
+-  char *domain;
+-  int parse_res;
++  /* If we read the entire database at setpwent time we just iterate
++     over the data we have in memory.  */
++  bool batch_read = intern.start != NULL;
+-  if (yp_get_default_domain (&domain))
++  char *domain = NULL;
++  if (!batch_read && __builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+   /* Get the next entry until we found a correct one. */
++  int parse_res;
+   do
+     {
+-      enum nss_status retval;
+-      char *result, *outkey, *result2, *p;
+-      int len, keylen, len2;
+-      size_t namelen;
++      char *result;
++      char *outkey;
++      int len;
++      int keylen;
+-      if (new_start)
+-        retval = yperr2nss (yp_first (domain, "passwd.byname",
+-                                      &outkey, &keylen, &result, &len));
++      if (batch_read)
++      {
++        struct response_t *bucket;
++
++      handle_batch_read:
++        bucket = intern.next;
++
++        if (__builtin_expect (intern.offset >= bucket->size, 0))
++          {
++            if (bucket->next == NULL)
++              return NSS_STATUS_NOTFOUND;
++
++            /* We look at all the content in the current bucket.  Go on
++               to the next.  */
++            bucket = intern.next = bucket->next;
++            intern.offset = 0;
++          }
++
++        for (result = &bucket->mem[intern.offset]; isspace (*result);
++             ++result)
++          ++intern.offset;
++
++        len = strlen (result);
++      }
+       else
+-        retval = yperr2nss ( yp_next (domain, "passwd.byname",
+-                                      oldkey, oldkeylen,
+-                                      &outkey, &keylen, &result, &len));
+-
+-      if (retval != NSS_STATUS_SUCCESS)
+-        {
+-          if (retval == NSS_STATUS_TRYAGAIN)
+-            *errnop = errno;
+-          return retval;
+-        }
++      {
++        int yperr;
++
++        if (new_start)
++          {
++            /* Maybe we should read the database in one piece.  */
++            if ((_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
++                && internal_nis_setpwent () == NSS_STATUS_SUCCESS
++                && intern.start != NULL)
++              {
++                batch_read = true;
++                goto handle_batch_read;
++              }
++
++            yperr = yp_first (domain, "passwd.byname", &outkey, &keylen,
++                              &result, &len);
++          }
++        else
++          yperr = yp_next (domain, "passwd.byname", oldkey, oldkeylen,
++                           &outkey, &keylen, &result, &len);
++
++        if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
++          {
++            enum nss_status retval = yperr2nss (yperr);
++
++            if (retval == NSS_STATUS_TRYAGAIN)
++              *errnop = errno;
++            return retval;
++          }
++      }
+       /* Check for adjunct style secret passwords.  They can be
+        recognized by a password starting with "##".  */
+-      p = strchr (result, ':');
++      char *p = strchr (result, ':');
++      size_t namelen;
++      char *result2;
++      int len2;
+       if (p != NULL   /* This better should be true in all cases.  */
+         && p[1] == '#' && p[2] == '#'
+         && (namelen = p - result,
+@@ -128,7 +293,8 @@ internal_nis_getpwent_r (struct passwd *
+           }
+         restlen = len - (p - result);
+-        if ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen)
++        if (__builtin_expect ((size_t) (namelen + (endp - encrypted)
++                                        + restlen + 2) > buflen, 0))
+           {
+             free (result2);
+             free (result);
+@@ -136,10 +302,10 @@ internal_nis_getpwent_r (struct passwd *
+             return NSS_STATUS_TRYAGAIN;
+           }
+-        __mempcpy (__mempcpy (__mempcpy (__mempcpy (buffer, result, namelen),
+-                                         ":", 1),
+-                              encrypted, endp - encrypted),
+-                   p, restlen + 1);
++        mempcpy (mempcpy (mempcpy (mempcpy (buffer, result, namelen),
++                                   ":", 1),
++                          encrypted, endp - encrypted),
++                 p, restlen + 1);
+         p = buffer;
+         free (result2);
+@@ -147,33 +313,41 @@ internal_nis_getpwent_r (struct passwd *
+       else
+       {
+       non_adjunct:
+-        if ((size_t) (len + 1) > buflen)
++        if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+           {
+             free (result);
+             *errnop = ERANGE;
+             return NSS_STATUS_TRYAGAIN;
+           }
+-        p = strncpy (buffer, result, len);
+-        buffer[len] = '\0';
++        p = buffer;
++        *((char *) mempcpy (buffer, result, len)) = '\0';
+       }
+       while (isspace (*p))
+         ++p;
+-      free (result);
++      if (!batch_read)
++      free (result);
+-      parse_res = _nss_files_parse_pwent (p, pwd, data, buflen, errnop);
+-      if (parse_res == -1)
++      parse_res = _nss_files_parse_pwent (p, pwd, (void *) buffer, buflen,
++                                        errnop);
++      if (__builtin_expect (parse_res == -1, 0))
+       {
+-        free (outkey);
++        if (!batch_read)
++          free (outkey);
+         *errnop = ERANGE;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      free (oldkey);
+-      oldkey = outkey;
+-      oldkeylen = keylen;
+-      new_start = 0;
++      if (batch_read)
++      intern.offset += len + 1;
++      else
++      {
++        free (oldkey);
++        oldkey = outkey;
++        oldkeylen = keylen;
++        new_start = 0;
++      }
+     }
+   while (parse_res < 1);
+@@ -199,28 +373,26 @@ enum nss_status
+ _nss_nis_getpwnam_r (const char *name, struct passwd *pwd,
+                    char *buffer, size_t buflen, int *errnop)
+ {
+-  struct parser_data *data = (void *) buffer;
+-  enum nss_status retval;
+-  char *domain, *result, *result2, *p;
+-  int len, len2, parse_res;
+-  size_t namelen;
+-
+   if (name == NULL)
+     {
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+     }
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+-  namelen = strlen (name);
++  size_t namelen = strlen (name);
+-  retval = yperr2nss (yp_match (domain, "passwd.byname", name,
+-                              namelen, &result, &len));
++  char *result;
++  int len;
++  int yperr = yp_match (domain, "passwd.byname", name, namelen, &result, &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+       *errnop = errno;
+       return retval;
+@@ -228,7 +400,9 @@ _nss_nis_getpwnam_r (const char *name, s
+   /* Check for adjunct style secret passwords.  They can be recognized
+      by a password starting with "##".  */
+-  p = strchr (result, ':');
++  char *result2;
++  int len2;
++  char *p = strchr (result, ':');
+   if (p != NULL       /* This better should be true in all cases.  */
+       && p[1] == '#' && p[2] == '#'
+       && yp_match (domain, "passwd.adjunct.byname", name, namelen,
+@@ -238,7 +412,6 @@ _nss_nis_getpwnam_r (const char *name, s
+        therein into original result.  */
+       char *encrypted = strchr (result2, ':');
+       char *endp;
+-      size_t restlen;
+       if (encrypted == NULL
+         || (endp = strchr (++encrypted, ':')) == NULL
+@@ -251,8 +424,9 @@ _nss_nis_getpwnam_r (const char *name, s
+         goto non_adjunct;
+       }
+-      restlen = len - (p - result);
+-      if ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen)
++      size_t restlen = len - (p - result);
++      if (__builtin_expect ((size_t) (namelen + (endp - encrypted)
++                                    + restlen + 2) > buflen, 0))
+       {
+         free (result2);
+         free (result);
+@@ -271,7 +445,7 @@ _nss_nis_getpwnam_r (const char *name, s
+   else
+     {
+     non_adjunct:
+-      if ((size_t) (len + 1) > buflen)
++      if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+       {
+         free (result);
+         *errnop = ERANGE;
+@@ -286,8 +460,9 @@ _nss_nis_getpwnam_r (const char *name, s
+     ++p;
+   free (result);
+-  parse_res = _nss_files_parse_pwent (p, pwd, data, buflen, errnop);
+-  if (parse_res < 1)
++  int parse_res = _nss_files_parse_pwent (p, pwd, (void *) buffer, buflen,
++                                        errnop);
++  if (__builtin_expect (parse_res < 1, 0))
+     {
+       if (parse_res == -1)
+         return NSS_STATUS_TRYAGAIN;
+@@ -302,23 +477,21 @@ enum nss_status
+ _nss_nis_getpwuid_r (uid_t uid, struct passwd *pwd,
+                    char *buffer, size_t buflen, int *errnop)
+ {
+-  struct parser_data *data = (void *) buffer;
+-  enum nss_status retval;
+-  char *domain, *result, *p, *result2;
+-  int len, nlen, parse_res, len2;
+-  char buf[32];
+-  size_t namelen;
+-
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+-  nlen = sprintf (buf, "%lu", (unsigned long int) uid);
++  char buf[32];
++  int nlen = snprintf (buf, sizeof (buf), "%lu", (unsigned long int) uid);
+-  retval = yperr2nss (yp_match (domain, "passwd.byuid", buf,
+-                              nlen, &result, &len));
++  char *result;
++  int len;
++  int yperr = yp_match (domain, "passwd.byuid", buf, nlen, &result, &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+       *errnop = errno;
+       return retval;
+@@ -326,7 +499,10 @@ _nss_nis_getpwuid_r (uid_t uid, struct p
+   /* Check for adjunct style secret passwords.  They can be recognized
+      by a password starting with "##".  */
+-  p = strchr (result, ':');
++  char *result2;
++  int len2;
++  size_t namelen;
++  char *p = strchr (result, ':');
+   if (p != NULL       /* This better should be true in all cases.  */
+       && p[1] == '#' && p[2] == '#'
+       && (namelen = p - result,
+@@ -351,7 +527,8 @@ _nss_nis_getpwuid_r (uid_t uid, struct p
+       }
+       restlen = len - (p - result);
+-      if ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen)
++      if (__builtin_expect ((size_t) (namelen + (endp - encrypted)
++                                    + restlen + 2) > buflen, 0))
+       {
+         free (result2);
+         free (result);
+@@ -370,7 +547,7 @@ _nss_nis_getpwuid_r (uid_t uid, struct p
+   else
+     {
+     non_adjunct:
+-      if ((size_t) (len + 1) > buflen)
++      if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+       {
+         free (result);
+         *errnop = ERANGE;
+@@ -385,8 +562,9 @@ _nss_nis_getpwuid_r (uid_t uid, struct p
+     ++p;
+   free (result);
+-  parse_res = _nss_files_parse_pwent (p, pwd, data, buflen, errnop);
+-  if (parse_res < 1)
++  int parse_res = _nss_files_parse_pwent (p, pwd, (void *) buffer, buflen,
++                                        errnop);
++  if (__builtin_expect (parse_res < 1, 0))
+     {
+       if (parse_res == -1)
+         return NSS_STATUS_TRYAGAIN;
+--- libc/nis/nss_nis/nis-rpc.c 2 Apr 2004 15:09:32 -0000       1.19
++++ libc/nis/nss_nis/nis-rpc.c 29 Apr 2006 01:12:53 -0000      1.21
+@@ -35,59 +36,22 @@
+ __libc_lock_define_initialized (static, lock)
+-struct response_t
+-{
+-  struct response_t *next;
+-  char val[0];
+-};
+-
+-struct intern_t
+-{
+-  struct response_t *start;
+-  struct response_t *next;
+-};
+-typedef struct intern_t intern_t;
+-
+-static intern_t intern = {NULL, NULL};
+-
+-static int
+-saveit (int instatus, char *inkey, int inkeylen, char *inval,
+-        int invallen, char *indata)
+-{
+-  intern_t *intern = (intern_t *)indata;
+-
+-  if (instatus != YP_TRUE)
+-    return 1;
++static intern_t intern;
+-  if (inkey && inkeylen > 0 && inval && invallen > 0)
+-    {
+-      struct response_t *newp = malloc (sizeof (struct response_t)
+-                                      + invallen + 1);
+-      if (newp == NULL)
+-      return 1; /* We have no error code for out of memory */
+-
+-      if (intern->start == NULL)
+-      intern->start = newp;
+-      else
+-      intern->next->next = newp;
+-      intern->next = newp;
+-
+-      newp->next = NULL;
+-      *((char *) mempcpy (newp->val, inval, invallen)) = '\0';
+-    }
+-
+-  return 0;
+-}
+ static void
+ internal_nis_endrpcent (intern_t *intern)
+ {
+-  while (intern->start != NULL)
++  struct response_t *curr = intern->next;
++
++  while (curr != NULL)
+     {
+-      intern->next = intern->start;
+-      intern->start = intern->start->next;
+-      free (intern->next);
++      struct response_t *last = curr;
++      curr = curr->next;
++      free (last);
+     }
++
++  intern->next = intern->start = NULL;
+ }
+ static enum nss_status
+@@ -102,10 +66,16 @@ internal_nis_setrpcent (intern_t *intern
+   internal_nis_endrpcent (intern);
+-  ypcb.foreach = saveit;
+-  ypcb.data = (char *)intern;
+-  status = yperr2nss (yp_all(domainname, "rpc.bynumber", &ypcb));
++  ypcb.foreach = _nis_saveit;
++  ypcb.data = (char *) intern;
++  status = yperr2nss (yp_all (domainname, "rpc.bynumber", &ypcb));
++
++  /* Mark the last buffer as full.  */
++  if (intern->next != NULL)
++    intern->next->size = intern->offset;
++
+   intern->next = intern->start;
++  intern->offset = 0;
+   return status;
+ }
+@@ -138,29 +108,56 @@ _nss_nis_endrpcent (void)
+ static enum nss_status
+ internal_nis_getrpcent_r (struct rpcent *rpc, char *buffer, size_t buflen,
+-                        int *errnop, intern_t *data)
++                        int *errnop, intern_t *intern)
+ {
+   struct parser_data *pdata = (void *) buffer;
+   int parse_res;
+   char *p;
+-  if (data->start == NULL)
+-    internal_nis_setrpcent (data);
++  if (intern->start == NULL)
++    internal_nis_setrpcent (intern);
+   /* Get the next entry until we found a correct one. */
+   do
+     {
+-      if (data->next == NULL)
+-      return NSS_STATUS_NOTFOUND;
++      struct response_t *bucket = intern->next;
++
++      if (__builtin_expect (intern->offset >= bucket->size, 0))
++      {
++        if (bucket->next == NULL)
++          return NSS_STATUS_NOTFOUND;
+-      p = strncpy (buffer, data->next->val, buflen);
+-      while (isspace (*p))
+-        ++p;
++        /* We look at all the content in the current bucket.  Go on
++           to the next.  */
++        bucket = intern->next = bucket->next;
++        intern->offset = 0;
++      }
++
++      for (p = &bucket->mem[intern->offset]; isspace (*p); ++p)
++        ++intern->offset;
++
++      size_t len = strlen (p) + 1;
++      if (__builtin_expect (len > buflen, 0))
++      {
++        *errnop = ERANGE;
++        return NSS_STATUS_TRYAGAIN;
++      }
++
++      /* We unfortunately have to copy the data in the user-provided
++       buffer because that buffer might be around for a very long
++       time and the servent structure must remain valid.  If we would
++       rely on the BUCKET memory the next 'setservent' or 'endservent'
++       call would destroy it.
++
++       The important thing is that it is a single NUL-terminated
++       string.  This is what the parsing routine expects.  */
++      p = memcpy (buffer, &bucket->mem[intern->offset], len);
+       parse_res = _nss_files_parse_rpcent (p, rpc, pdata, buflen, errnop);
+-      if (parse_res == -1)
++      if (__builtin_expect (parse_res == -1, 0))
+       return NSS_STATUS_TRYAGAIN;
+-      data->next = data->next->next;
++
++      intern->offset += len;
+     }
+   while (!parse_res);
+@@ -186,21 +183,18 @@ enum nss_status
+ _nss_nis_getrpcbyname_r (const char *name, struct rpcent *rpc,
+                        char *buffer, size_t buflen, int *errnop)
+ {
+-  intern_t data = {NULL, NULL};
+-  enum nss_status status;
+-  int found;
+-
+   if (name == NULL)
+     {
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+     }
+-  status = internal_nis_setrpcent (&data);
+-  if (status != NSS_STATUS_SUCCESS)
++  intern_t data = { NULL, NULL, 0 };
++  enum nss_status status = internal_nis_setrpcent (&data);
++  if (__builtin_expect (status != NSS_STATUS_SUCCESS, 0))
+     return status;
+-  found = 0;
++  int found = 0;
+   while (!found &&
+          ((status = internal_nis_getrpcent_r (rpc, buffer, buflen, errnop,
+                                             &data)) == NSS_STATUS_SUCCESS))
+@@ -226,53 +220,52 @@ _nss_nis_getrpcbyname_r (const char *nam
+   internal_nis_endrpcent (&data);
+-  if (!found && status == NSS_STATUS_SUCCESS)
++  if (__builtin_expect (!found && status == NSS_STATUS_SUCCESS, 0))
+     return NSS_STATUS_NOTFOUND;
+-  else
+-    return status;
++
++  return status;
+ }
+ enum nss_status
+ _nss_nis_getrpcbynumber_r (int number, struct rpcent *rpc,
+                          char *buffer, size_t buflen, int *errnop)
+ {
+-  struct parser_data *data = (void *) buffer;
+-  enum nss_status retval;
+-  char *domain, *result, *p;
+-  int len, nlen, parse_res;
+-  char buf[32];
+-
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+-  nlen = sprintf (buf, "%d", number);
++  char buf[32];
++  int nlen = snprintf (buf, sizeof (buf), "%d", number);
+-  retval = yperr2nss (yp_match (domain, "rpc.bynumber", buf,
+-                               nlen, &result, &len));
++  char *result;
++  int len;
++  int yperr = yp_match (domain, "rpc.bynumber", buf, nlen, &result, &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+       *errnop = errno;
+       return retval;
+     }
+-  if ((size_t) (len + 1) > buflen)
++  if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+     {
+       free (result);
+       *errnop = ERANGE;
+       return NSS_STATUS_TRYAGAIN;
+     }
+-  p = strncpy (buffer, result, len);
++  char *p = strncpy (buffer, result, len);
+   buffer[len] = '\0';
+   while (isspace (*p))
+     ++p;
+   free (result);
+-  parse_res = _nss_files_parse_rpcent (p, rpc, data, buflen, errnop);
+-
+-  if (parse_res < 1)
++  int parse_res = _nss_files_parse_rpcent (p, rpc, (void  *) buffer, buflen,
++                                         errnop);
++  if (__builtin_expect (parse_res < 1, 0))
+     {
+       if (parse_res == -1)
+       return NSS_STATUS_TRYAGAIN;
+--- libc/nis/nss_nis/nis-service.c     2 Apr 2004 15:09:32 -0000       1.27
++++ libc/nis/nss_nis/nis-service.c     29 Apr 2006 01:11:05 -0000      1.33
+@@ -27,6 +27,7 @@
+ #include <rpcsvc/ypclnt.h>
+ #include "nss-nis.h"
++#include <libnsl.h>
+ /* Get the declaration of the parser function.  */
+@@ -36,20 +37,7 @@
+ __libc_lock_define_initialized (static, lock)
+-struct response_t
+-{
+-  struct response_t *next;
+-  char val[0];
+-};
+-
+-struct intern_t
+-{
+-  struct response_t *start;
+-  struct response_t *next;
+-};
+-typedef struct intern_t intern_t;
+-
+-static intern_t intern = { NULL, NULL };
++static intern_t intern;
+ struct search_t
+ {
+@@ -64,63 +52,31 @@ struct search_t
+ };
+ static int
+-saveit (int instatus, char *inkey, int inkeylen, char *inval,
+-        int invallen, char *indata)
+-{
+-  intern_t *intern = (intern_t *) indata;
+-
+-  if (instatus != YP_TRUE)
+-    return 1;
+-
+-  if (inkey && inkeylen > 0 && inval && invallen > 0)
+-    {
+-      struct response_t *newp = malloc (sizeof (struct response_t)
+-                                      + invallen + 1);
+-      if (newp == NULL)
+-      return 1; /* We have no error code for out of memory */
+-
+-      if (intern->start == NULL)
+-      intern->start = newp;
+-      else
+-      intern->next->next = newp;
+-      intern->next = newp;
+-
+-      newp->next = NULL;
+-      *((char *) mempcpy (newp->val, inval, invallen)) = '\0';
+-    }
+-
+-  return 0;
+-}
+-
+-static int
+ dosearch (int instatus, char *inkey, int inkeylen, char *inval,
+         int invallen, char *indata)
+ {
+   struct search_t *req = (struct search_t *) indata;
+-  if (instatus != YP_TRUE)
++  if (__builtin_expect (instatus != YP_TRUE, 0))
+     return 1;
+   if (inkey && inkeylen > 0 && inval && invallen > 0)
+     {
+-      struct parser_data *pdata = (void *) req->buffer;
+-      int parse_res;
+-      char *p;
+-
+-      if ((size_t) (invallen + 1) > req->buflen)
++      if (__builtin_expect ((size_t) (invallen + 1) > req->buflen, 0))
+       {
+         *req->errnop = ERANGE;
+         req->status = NSS_STATUS_TRYAGAIN;
+         return 1;
+       }
+-      p = strncpy (req->buffer, inval, invallen);
++      char *p = strncpy (req->buffer, inval, invallen);
+       req->buffer[invallen] = '\0';
+       while (isspace (*p))
+         ++p;
+-      parse_res = _nss_files_parse_servent (p, req->serv, pdata, req->buflen,
+-                                          req->errnop);
++      int parse_res = _nss_files_parse_servent (p, req->serv,
++                                              (void *) req->buffer,
++                                              req->buflen, req->errnop);
+       if (parse_res == -1)
+       {
+         req->status = NSS_STATUS_TRYAGAIN;
+@@ -154,35 +110,35 @@ dosearch (int instatus, char *inkey, int
+   return 0;
+ }
+-static enum nss_status
+-internal_nis_endservent (intern_t * intern)
++static void
++internal_nis_endservent (void)
+ {
+-  while (intern->start != NULL)
++  struct response_t *curr = intern.next;
++
++  while (curr != NULL)
+     {
+-      intern->next = intern->start;
+-      intern->start = intern->start->next;
+-      free (intern->next);
++      struct response_t *last = curr;
++      curr = curr->next;
++      free (last);
+     }
+-  return NSS_STATUS_SUCCESS;
++  intern.next = intern.start = NULL;
+ }
+ enum nss_status
+ _nss_nis_endservent (void)
+ {
+-  enum nss_status status;
+-
+   __libc_lock_lock (lock);
+-  status = internal_nis_endservent (&intern);
++  internal_nis_endservent ();
+   __libc_lock_unlock (lock);
+-  return status;
++  return NSS_STATUS_SUCCESS;
+ }
+ static enum nss_status
+-internal_nis_setservent (intern_t *intern)
++internal_nis_setservent (void)
+ {
+   char *domainname;
+   struct ypall_callback ypcb;
+@@ -191,12 +147,18 @@ internal_nis_setservent (intern_t *inter
+   if (yp_get_default_domain (&domainname))
+     return NSS_STATUS_UNAVAIL;
+-  (void) internal_nis_endservent (intern);
++  internal_nis_endservent ();
+-  ypcb.foreach = saveit;
+-  ypcb.data = (char *) intern;
++  ypcb.foreach = _nis_saveit;
++  ypcb.data = (char *) &intern;
+   status = yperr2nss (yp_all (domainname, "services.byname", &ypcb));
+-  intern->next = intern->start;
++
++  /* Mark the last buffer as full.  */
++  if (intern.next != NULL)
++    intern.next->size = intern.offset;
++
++  intern.next = intern.start;
++  intern.offset = 0;
+   return status;
+ }
+@@ -208,7 +170,7 @@ _nss_nis_setservent (int stayopen)
+   __libc_lock_lock (lock);
+-  status = internal_nis_setservent (&intern);
++  status = internal_nis_setservent ();
+   __libc_lock_unlock (lock);
+@@ -217,29 +179,56 @@ _nss_nis_setservent (int stayopen)
+ static enum nss_status
+ internal_nis_getservent_r (struct servent *serv, char *buffer,
+-                         size_t buflen, int *errnop, intern_t *data)
++                         size_t buflen, int *errnop)
+ {
+   struct parser_data *pdata = (void *) buffer;
+   int parse_res;
+   char *p;
+-  if (data->start == NULL)
+-    internal_nis_setservent (data);
++  if (intern.start == NULL)
++    internal_nis_setservent ();
+-  /* Get the next entry until we found a correct one. */
++  /* Get the next entry until we found a correct one.  */
+   do
+     {
+-      if (data->next == NULL)
+-      return NSS_STATUS_NOTFOUND;
++      struct response_t *bucket = intern.next;
+-      p = strncpy (buffer, data->next->val, buflen);
+-      while (isspace (*p))
+-        ++p;
++      if (__builtin_expect (intern.offset >= bucket->size, 0))
++      {
++        if (bucket->next == NULL)
++          return NSS_STATUS_NOTFOUND;
++
++        /* We look at all the content in the current bucket.  Go on
++           to the next.  */
++        bucket = intern.next = bucket->next;
++        intern.offset = 0;
++      }
++
++      for (p = &bucket->mem[intern.offset]; isspace (*p); ++p)
++        ++intern.offset;
++
++      size_t len = strlen (p) + 1;
++      if (__builtin_expect (len > buflen, 0))
++      {
++        *errnop = ERANGE;
++        return NSS_STATUS_TRYAGAIN;
++      }
++
++      /* We unfortunately have to copy the data in the user-provided
++       buffer because that buffer might be around for a very long
++       time and the servent structure must remain valid.  If we would
++       rely on the BUCKET memory the next 'setservent' or 'endservent'
++       call would destroy it.
++
++       The important thing is that it is a single NUL-terminated
++       string.  This is what the parsing routine expects.  */
++      p = memcpy (buffer, &bucket->mem[intern.offset], len);
+       parse_res = _nss_files_parse_servent (p, serv, pdata, buflen, errnop);
+-      if (parse_res == -1)
++      if (__builtin_expect (parse_res == -1, 0))
+         return NSS_STATUS_TRYAGAIN;
+-      data->next = data->next->next;
++
++      intern.offset += len;
+     }
+   while (!parse_res);
+@@ -254,7 +243,7 @@ _nss_nis_getservent_r (struct servent *s
+   __libc_lock_lock (lock);
+-  status = internal_nis_getservent_r (serv, buffer, buflen, errnop, &intern);
++  status = internal_nis_getservent_r (serv, buffer, buflen, errnop);
+   __libc_lock_unlock (lock);
+@@ -266,60 +255,56 @@ _nss_nis_getservbyname_r (const char *na
+                         struct servent *serv, char *buffer, size_t buflen,
+                         int *errnop)
+ {
+-  enum nss_status status;
+-  char *domain;
+-
+   if (name == NULL)
+     {
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+     }
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+   /* If the protocol is given, we could try if our NIS server knows
+      about services.byservicename map. If yes, we only need one query.  */
+-  char key[strlen (name) + (protocol ? strlen (protocol) : 0) + 2];
+-  char *cp, *result;
+-  size_t keylen, len;
+-  int int_len;
++  size_t keylen = strlen (name) + 1 + (protocol ? strlen (protocol) : 0);
++  char key[keylen + 1];
+   /* key is: "name/proto" */
+-  cp = stpcpy (key, name);
+-  if (protocol)
++  char *cp = stpcpy (key, name);
++  if (protocol != NULL)
+     {
+       *cp++ = '/';
+       strcpy (cp, protocol);
+     }
+-  keylen = strlen (key);
+-  status = yperr2nss (yp_match (domain, "services.byservicename", key,
+-                              keylen, &result, &int_len));
+-  len = int_len;
++
++  char *result;
++  int int_len;
++  enum nss_status status = yperr2nss (yp_match (domain,
++                                              "services.byservicename", key,
++                                              keylen, &result, &int_len));
++  size_t len = int_len;
+   /* If we found the key, it's ok and parse the result. If not,
+      fall through and parse the complete table. */
+-  if (status == NSS_STATUS_SUCCESS)
++  if (__builtin_expect (status == NSS_STATUS_SUCCESS, 1))
+     {
+-      struct parser_data *pdata = (void *) buffer;
+-      int parse_res;
+-      char *p;
+-
+-      if ((size_t) (len + 1) > buflen)
++      if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+       {
+         free (result);
+         *errnop = ERANGE;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      p = strncpy (buffer, result, len);
++      char *p = strncpy (buffer, result, len);
+       buffer[len] = '\0';
+       while (isspace (*p))
+       ++p;
+       free (result);
+-      parse_res = _nss_files_parse_servent (p, serv, pdata,
+-                                          buflen, errnop);
+-      if (parse_res < 0)
++
++      int parse_res = _nss_files_parse_servent (p, serv, (void *) buffer,
++                                              buflen, errnop);
++      if (__builtin_expect (parse_res < 0, 0))
+       {
+         if (parse_res == -1)
+           return NSS_STATUS_TRYAGAIN;
+@@ -331,7 +316,7 @@ _nss_nis_getservbyname_r (const char *na
+     }
+   /* Check if it is safe to rely on services.byservicename.  */
+-  if (_nis_default_nss () & NSS_FLAG_SERVICES_AUTHORITATIVE)
++  if (_nsl_default_nss () & NSS_FLAG_SERVICES_AUTHORITATIVE)
+     return status;
+   struct ypall_callback ypcb;
+@@ -360,10 +345,8 @@ _nss_nis_getservbyport_r (int port, cons
+                         struct servent *serv, char *buffer,
+                         size_t buflen, int *errnop)
+ {
+-  enum nss_status status;
+   char *domain;
+-
+-  if (yp_get_default_domain (&domain))
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+   /* If the protocol is given, we only need one query.
+@@ -372,48 +355,45 @@ _nss_nis_getservbyport_r (int port, cons
+   const char *proto = protocol != NULL ? protocol : "tcp";
+   do
+     {
++      /* key is: "port/proto" */
+       char key[sizeof (int) * 3 + strlen (proto) + 2];
++      size_t keylen = snprintf (key, sizeof (key), "%d/%s", ntohs (port),
++                              proto);
++
+       char *result;
+-      size_t keylen, len;
+       int int_len;
+-
+-      /* key is: "port/proto" */
+-      keylen = snprintf (key, sizeof (key), "%d/%s", ntohs (port), proto);
+-      status = yperr2nss (yp_match (domain, "services.byname", key,
+-                                  keylen, &result, &int_len));
+-      len = int_len;
++      enum nss_status status = yperr2nss (yp_match (domain, "services.byname",
++                                                  key, keylen, &result,
++                                                  &int_len));
++      size_t len = int_len;
+       /* If we found the key, it's ok and parse the result. If not,
+        fall through and parse the complete table. */
+       if (status == NSS_STATUS_SUCCESS)
+       {
+-        struct parser_data *pdata = (void *) buffer;
+-        int parse_res;
+-        char *p;
+-
+-        if ((size_t) (len + 1) > buflen)
++        if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+           {
+             free (result);
+             *errnop = ERANGE;
+             return NSS_STATUS_TRYAGAIN;
+           }
+-        p = strncpy (buffer, result, len);
++        char  *p = strncpy (buffer, result, len);
+         buffer[len] = '\0';
+         while (isspace (*p))
+           ++p;
+         free (result);
+-        parse_res = _nss_files_parse_servent (p, serv, pdata,
+-                                              buflen, errnop);
+-        if (parse_res < 0)
++        int parse_res = _nss_files_parse_servent (p, serv, (void *) buffer,
++                                                  buflen, errnop);
++        if (__builtin_expect (parse_res < 0, 0))
+           {
+             if (parse_res == -1)
+               return NSS_STATUS_TRYAGAIN;
+             else
+               return NSS_STATUS_NOTFOUND;
+           }
+-        else
+-          return NSS_STATUS_SUCCESS;
++
++        return NSS_STATUS_SUCCESS;
+       }
+     }
+   while (protocol == NULL && (proto[0] == 't' ? (proto = "udp") : NULL));
+@@ -434,7 +414,8 @@ _nss_nis_getservbyport_r (int port, cons
+   req.buflen = buflen;
+   req.errnop = errnop;
+   req.status = NSS_STATUS_NOTFOUND;
+-  status = yperr2nss (yp_all (domain, "services.byname", &ypcb));
++  enum nss_status status = yperr2nss (yp_all (domain, "services.byname",
++                                            &ypcb));
+   if (status != NSS_STATUS_SUCCESS)
+     return status;
+--- libc/nis/nss_nis/nis-spwd.c        19 Jan 2003 19:20:34 -0000      1.14
++++ libc/nis/nss_nis/nis-spwd.c        29 Apr 2006 01:09:49 -0000      1.16
+@@ -68,49 +68,52 @@ static enum nss_status
+ internal_nis_getspent_r (struct spwd *sp, char *buffer, size_t buflen,
+                        int *errnop)
+ {
+-  struct parser_data *data = (void *) buffer;
+-  char *domain, *result, *outkey;
+-  int len, keylen, parse_res;
+-
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+   /* Get the next entry until we found a correct one. */
++  int parse_res;
+   do
+     {
+-      enum nss_status retval;
+-      char *p;
++      char *result;
++      char *outkey;
++      int len;
++      int keylen;
++      int yperr;
+       if (new_start)
+-        retval = yperr2nss (yp_first (domain, "shadow.byname",
+-                                      &outkey, &keylen, &result, &len));
++        yperr = yp_first (domain, "shadow.byname", &outkey, &keylen, &result,
++                        &len);
+       else
+-        retval = yperr2nss ( yp_next (domain, "shadow.byname",
+-                                      oldkey, oldkeylen,
+-                                      &outkey, &keylen, &result, &len));
++        yperr = yp_next (domain, "shadow.byname", oldkey, oldkeylen, &outkey,
++                       &keylen, &result, &len);
+-      if (retval != NSS_STATUS_SUCCESS)
++      if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+         {
++        enum nss_status retval = yperr2nss (yperr);
++
+         if (retval == NSS_STATUS_TRYAGAIN)
+           *errnop = errno;
+           return retval;
+         }
+-      if ((size_t) (len + 1) > buflen)
++      if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+         {
+           free (result);
+         *errnop = ERANGE;
+           return NSS_STATUS_TRYAGAIN;
+         }
+-      p = strncpy (buffer, result, len);
++      char *p = strncpy (buffer, result, len);
+       buffer[len] = '\0';
+       while (isspace (*p))
+         ++p;
+       free (result);
+-      parse_res = _nss_files_parse_spent (p, sp, data, buflen, errnop);
+-      if (parse_res == -1)
++      parse_res = _nss_files_parse_spent (p, sp, (void *) buffer, buflen,
++                                        errnop);
++      if (__builtin_expect  (parse_res == -1, 0))
+       {
+         free (outkey);
+         *errnop = ERANGE;
+@@ -146,45 +149,46 @@ enum nss_status
+ _nss_nis_getspnam_r (const char *name, struct spwd *sp,
+                    char *buffer, size_t buflen, int *errnop)
+ {
+-  struct parser_data *data = (void *) buffer;
+-  enum nss_status retval;
+-  char *domain, *result, *p;
+-  int len, parse_res;
+-
+   if (name == NULL)
+     {
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+     }
+-  if (yp_get_default_domain (&domain))
++  char *domain;
++  if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+-  retval = yperr2nss (yp_match (domain, "shadow.byname", name,
+-                              strlen (name), &result, &len));
++  char *result;
++  int len;
++  int yperr = yp_match (domain, "shadow.byname", name, strlen (name), &result,
++                      &len);
+-  if (retval != NSS_STATUS_SUCCESS)
++  if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
++      enum nss_status retval = yperr2nss (yperr);
++
+       if (retval == NSS_STATUS_TRYAGAIN)
+       *errnop = errno;
+       return retval;
+     }
+-  if ((size_t) (len + 1) > buflen)
++  if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+     {
+       free (result);
+       *errnop = ERANGE;
+       return NSS_STATUS_TRYAGAIN;
+     }
+-  p = strncpy (buffer, result, len);
++  char *p = strncpy (buffer, result, len);
+   buffer[len] = '\0';
+   while (isspace (*p))
+     ++p;
+   free (result);
+-  parse_res = _nss_files_parse_spent (p, sp, data, buflen, errnop);
+-  if (parse_res < 1)
++  int parse_res = _nss_files_parse_spent (p, sp, (void *) buffer, buflen,
++                                        errnop);
++  if (__builtin_expect (parse_res < 1, 0))
+     {
+       if (parse_res == -1)
+       return NSS_STATUS_TRYAGAIN;
+--- libc/nis/nss_nisplus/nisplus-alias.c       7 Apr 2006 00:27:14 -0000       1.19
++++ libc/nis/nss_nisplus/nisplus-alias.c       14 Apr 2006 20:38:29 -0000      1.20
+@@ -36,11 +36,11 @@ static u_long next_entry;
+ static nis_name tablename_val;
+ static size_t tablename_len;
+-#define NISENTRYVAL(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
++#define NISENTRYVAL(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+-#define NISENTRYLEN(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
++#define NISENTRYLEN(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
+ static enum nss_status
+ _nss_create_tablename (int *errnop)
+@@ -79,16 +79,12 @@ _nss_nisplus_parse_aliasent (nis_result 
+     return 0;
+   if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+-      || __type_of (&result->objects.objects_val[entry]) != NIS_ENTRY_OBJ
+-      || strcmp (result->objects.objects_val[entry].EN_data.en_type,
++      || __type_of (&NIS_RES_OBJECT (result)[entry]) != NIS_ENTRY_OBJ
++      || strcmp (NIS_RES_OBJECT (result)[entry].EN_data.en_type,
+                "mail_aliases") != 0
+-      || result->objects.objects_val[entry].EN_data.en_cols.en_cols_len < 2)
++      || NIS_RES_OBJECT (result)[entry].EN_data.en_cols.en_cols_len < 2)
+     return 0;
+-  char *first_unused = buffer + NISENTRYLEN (0, 1, result) + 1;
+-  size_t room_left = (buflen - (buflen % __alignof__ (char *))
+-                    - NISENTRYLEN (0, 1, result) - 2);
+-
+   if (NISENTRYLEN (entry, 1, result) >= buflen)
+     {
+       /* The line is too long for our buffer.  */
+@@ -101,13 +97,15 @@ _nss_nisplus_parse_aliasent (nis_result 
+                       NISENTRYLEN (entry, 1, result));
+   *cp = '\0';
+-  if (NISENTRYLEN(entry, 0, result) >= room_left)
+-    goto no_more_room;
++  char *first_unused = cp + 1;
++  size_t room_left = buflen - (first_unused - buffer);
+   alias->alias_local = 0;
+   alias->alias_members_len = 0;
+-  *first_unused = '\0';
+-  ++first_unused;
++
++  if (NISENTRYLEN (entry, 0, result) >= room_left)
++    goto no_more_room;
++
+   cp = __stpncpy (first_unused, NISENTRYVAL (entry, 0, result),
+                 NISENTRYLEN (entry, 0, result));
+   *cp = '\0';
+@@ -118,11 +116,20 @@ _nss_nisplus_parse_aliasent (nis_result 
+   if (cp != NULL)
+     *cp = '\0';
+-  first_unused += strlen (alias->alias_name) +1;
++  size_t len = strlen (alias->alias_name) + 1;
++  first_unused += len;
++  room_left -= len;
++
+   /* Adjust the pointer so it is aligned for
+      storing pointers.  */
+-  first_unused += __alignof__ (char *) - 1;
+-  first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *));
++  size_t adjust = ((__alignof__ (char *)
++                  - (first_unused - (char *) 0) % __alignof__ (char *))
++                 % __alignof__ (char *));
++  if (room_left < adjust)
++    goto no_more_room;
++  first_unused += adjust;
++  room_left -= adjust;
++
+   alias->alias_members = (char **) first_unused;
+   char *line = buffer;
+@@ -146,8 +153,10 @@ _nss_nisplus_parse_aliasent (nis_result 
+       if (line != alias->alias_members[alias->alias_members_len])
+       {
+         *line++ = '\0';
+-        alias->alias_members_len++;
++        ++alias->alias_members_len;
+       }
++      else if (*line == ',')
++      ++line;
+     }
+   return alias->alias_members_len == 0 ? 0 : 1;
+--- libc/nis/nss_nisplus/nisplus-ethers.c      7 Apr 2006 00:23:49 -0000       1.24
++++ libc/nis/nss_nisplus/nisplus-ethers.c      30 Apr 2006 05:44:23 -0000      1.26
+@@ -38,11 +38,11 @@ static nis_name tablename_val;
+ static u_long tablename_len;
+-#define NISENTRYVAL(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
++#define NISENTRYVAL(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].zo_data.objdata_u.en_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+-#define NISENTRYLEN(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
++#define NISENTRYLEN(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].zo_data.objdata_u.en_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
+ static int
+ _nss_nisplus_parse_etherent (nis_result *result, struct etherent *ether,
+@@ -55,7 +55,7 @@ _nss_nisplus_parse_etherent (nis_result 
+     return 0;
+   if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+-      || result->objects.objects_len != 1
++      || NIS_RES_NUMOBJ (result) != 1
+       || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
+       || strcmp (NIS_RES_OBJECT (result)->EN_data.en_type,
+                "ethers_tbl") != 0
+@@ -63,13 +63,15 @@ _nss_nisplus_parse_etherent (nis_result 
+     return 0;
+   /* Generate the ether entry format and use the normal parser */
+-  if (NISENTRYLEN (0, 0, result) +1 > room_left)
++  if (NISENTRYLEN (0, 0, result) + 1 > room_left)
+     {
+       *errnop = ERANGE;
+       return -1;
+     }
+-  strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result));
+-  room_left -= (NISENTRYLEN (0, 0, result) +1);
++  char *cp = __stpncpy (p, NISENTRYVAL (0, 0, result),
++                      NISENTRYLEN (0, 0, result));
++  *cp = '\0';
++  room_left -= NISENTRYLEN (0, 0, result) + 1;
+   ether->e_name = p;
+   struct ether_addr *ea = ether_aton (NISENTRYVAL (0, 1, result));
+@@ -174,6 +176,11 @@ internal_nisplus_getetherent_r (struct e
+       {
+         saved_result = NULL;
+         result = nis_first_entry (tablename_val);
++        if (result == NULL)
++          {
++            *errnop = errno;
++            return NSS_STATUS_TRYAGAIN;
++          }
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           return niserr2nss (result->status);
+       }
+@@ -181,6 +188,11 @@ internal_nisplus_getetherent_r (struct e
+       {
+         saved_result = result;
+         result = nis_next_entry (tablename_val, &result->cookie);
++        if (result == NULL)
++          {
++            *errnop = errno;
++            return NSS_STATUS_TRYAGAIN;
++          }
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           {
+             nis_freeresult (saved_result);
+--- libc/nis/nss_nisplus/nisplus-hosts.c       25 Mar 2006 20:59:19 -0000      1.29
++++ libc/nis/nss_nisplus/nisplus-hosts.c       30 Apr 2006 05:44:23 -0000      1.31
+@@ -36,15 +36,16 @@ static nis_result *result;
+ static nis_name tablename_val;
+ static u_long tablename_len;
+-#define NISENTRYVAL(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
++#define NISENTRYVAL(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+-#define NISENTRYLEN(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
++#define NISENTRYLEN(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
+ /* Get implementation for some internal functions. */
+ #include <resolv/mapv4v6addr.h>
++
+ static int
+ _nss_nisplus_parse_hostent (nis_result *result, int af, struct hostent *host,
+                           char *buffer, size_t buflen, int *errnop,
+@@ -53,27 +54,26 @@ _nss_nisplus_parse_hostent (nis_result *
+   unsigned int i;
+   char *first_unused = buffer;
+   size_t room_left = buflen;
+-  char *data, *p, *line;
+   if (result == NULL)
+     return 0;
+   if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
+-      __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ ||
+-      strcmp(result->objects.objects_val[0].EN_data.en_type,
+-           "hosts_tbl") != 0 ||
+-      result->objects.objects_val[0].EN_data.en_cols.en_cols_len < 4)
++      __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ ||
++      strcmp(NIS_RES_OBJECT (result)[0].EN_data.en_type, "hosts_tbl") != 0 ||
++      NIS_RES_OBJECT (result)[0].EN_data.en_cols.en_cols_len < 4)
+     return 0;
+-  if (room_left < NISENTRYLEN (0, 2, result) + 1)
++  char *data = first_unused;
++
++  if (room_left < (af == AF_INET6 || (flags & AI_V4MAPPED) != 0
++                 ? IN6ADDRSZ : INADDRSZ))
+     {
+     no_more_room:
+       *errnop = ERANGE;
+       return -1;
+     }
+-  data = first_unused;
+-
+   /* Parse address.  */
+   if (af == AF_INET && inet_pton (af, NISENTRYVAL (0, 2, result), data) > 0)
+     {
+@@ -99,51 +99,53 @@ _nss_nisplus_parse_hostent (nis_result *
+     /* Illegal address: ignore line.  */
+     return 0;
+-  first_unused+=host->h_length;
+-  room_left-=host->h_length;
++  first_unused += host->h_length;
++  room_left -= host->h_length;
+   if (NISENTRYLEN (0, 0, result) + 1 > room_left)
+     goto no_more_room;
+-  p = __stpncpy (first_unused, NISENTRYVAL (0, 0, result),
+-               NISENTRYLEN (0, 0, result));
+-  *p = '\0';
+-  room_left -= (NISENTRYLEN (0, 0, result) + 1);
+   host->h_name = first_unused;
+-  first_unused += NISENTRYLEN (0, 0, result) +1;
+-  p = first_unused;
+-
+-  line = p;
+-  for (i = 0; i < result->objects.objects_len; ++i)
++  first_unused = __stpncpy (first_unused, NISENTRYVAL (0, 0, result),
++                          NISENTRYLEN (0, 0, result));
++  *first_unused++ = '\0';
++  room_left -= NISENTRYLEN (0, 0, result) + 1;
++
++  /* XXX Rewrite at some point to allocate the array first and then
++     copy the strings.  It wasteful to first concatenate the strings
++     to just split them again later.  */
++  char *line = first_unused;
++  for (i = 0; i < NIS_RES_NUMOBJ (result); ++i)
+     {
+       if (strcmp (NISENTRYVAL (i, 1, result), host->h_name) != 0)
+       {
+         if (NISENTRYLEN (i, 1, result) + 2 > room_left)
+           goto no_more_room;
+-        *p++ = ' ';
+-        p = __stpncpy (p, NISENTRYVAL (i, 1, result),
+-                       NISENTRYLEN (i, 1, result));
+-        *p = '\0';
+-        room_left -= (NISENTRYLEN (i, 1, result) + 1);
++        *first_unused++ = ' ';
++        first_unused = __stpncpy (first_unused, NISENTRYVAL (i, 1, result),
++                                  NISENTRYLEN (i, 1, result));
++        *first_unused = '\0';
++        room_left -= NISENTRYLEN (i, 1, result) + 1;
+       }
+     }
+-  *p++ = '\0';
+-  first_unused = p;
++  *first_unused++ = '\0';
+   /* Adjust the pointer so it is aligned for
+      storing pointers.  */
+-  first_unused += __alignof__ (char *) - 1;
+-  first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *));
+-  host->h_addr_list = (char **) first_unused;
+-  if (room_left < 2 * sizeof (char *))
++  size_t adjust = ((__alignof__ (char *)
++                  - (first_unused - (char *) 0) % __alignof__ (char *))
++                 % __alignof__ (char *));
++  if (room_left < adjust + 3 * sizeof (char *))
+     goto no_more_room;
++  first_unused += adjust;
++  room_left -= adjust;
++  host->h_addr_list = (char **) first_unused;
+-  room_left -= (2 * sizeof (char *));
++  room_left -= 3 * sizeof (char *);
+   host->h_addr_list[0] = data;
+   host->h_addr_list[1] = NULL;
+   host->h_aliases = &host->h_addr_list[2];
+-  host->h_aliases[0] = NULL;
+   i = 0;
+   while (*line != '\0')
+@@ -159,23 +161,21 @@ _nss_nisplus_parse_hostent (nis_result *
+       goto no_more_room;
+       room_left -= sizeof (char *);
+-      host->h_aliases[i] = line;
++      host->h_aliases[i++] = line;
+       while (*line != '\0' && *line != ' ')
+       ++line;
+       if (*line == ' ')
+-      {
+-        *line = '\0';
+-        ++line;
+-        ++i;
+-      }
+-      else
+-      host->h_aliases[i+1] = NULL;
++      *line++ = '\0';
+     }
++
++  host->h_aliases[i] = NULL;
++
+   return 1;
+ }
++
+ static enum nss_status
+ _nss_create_tablename (int *errnop)
+ {
+@@ -265,6 +265,11 @@ internal_nisplus_gethostent_r (struct ho
+           }
+         result = nis_first_entry (tablename_val);
++        if (result == NULL)
++          {
++            *errnop = errno;
++            return NSS_STATUS_TRYAGAIN;
++          }
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+             {
+               enum nss_status retval = niserr2nss (result->status);
+@@ -279,11 +284,13 @@ internal_nisplus_gethostent_r (struct ho
+       }
+       else
+       {
+-        nis_result *res2;
+-
+         saved_res = result;
+-        res2 = nis_next_entry(tablename_val, &result->cookie);
+-        result = res2;
++        result = nis_next_entry (tablename_val, &result->cookie);
++        if (result == NULL)
++          {
++            *errnop = errno;
++            return NSS_STATUS_TRYAGAIN;
++          }
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+             {
+               enum nss_status retval= niserr2nss (result->status);
+--- libc/nis/nss_nisplus/nisplus-netgrp.c      3 Dec 2005 22:11:34 -0000       1.16
++++ libc/nis/nss_nisplus/nisplus-netgrp.c      24 Apr 2006 04:22:52 -0000      1.17
+@@ -27,11 +27,11 @@
+ #include "nss-nisplus.h"
+-#define NISENTRYVAL(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
++#define NISENTRYVAL(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+-#define NISENTRYLEN(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
++#define NISENTRYLEN(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
+ enum nss_status
+ _nss_nisplus_getnetgrent_r (struct __netgrent *result, char *buffer,
+--- libc/nis/nss_nisplus/nisplus-network.c     7 Apr 2006 00:14:50 -0000       1.23
++++ libc/nis/nss_nisplus/nisplus-network.c     30 Apr 2006 05:44:23 -0000      1.25
+@@ -36,11 +36,11 @@ static nis_result *result;
+ static nis_name tablename_val;
+ static u_long tablename_len;
+-#define NISENTRYVAL(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
++#define NISENTRYVAL(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+-#define NISENTRYLEN(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
++#define NISENTRYLEN(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
+ static int
+@@ -54,10 +54,10 @@ _nss_nisplus_parse_netent (nis_result *r
+     return 0;
+   if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+-      || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
+-      || strcmp (result->objects.objects_val[0].EN_data.en_type,
++      || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
++      || strcmp (NIS_RES_OBJECT (result)[0].EN_data.en_type,
+                "networks_tbl") != 0
+-      || result->objects.objects_val[0].EN_data.en_cols.en_cols_len < 3)
++      || NIS_RES_OBJECT (result)[0].EN_data.en_cols.en_cols_len < 3)
+     return 0;
+   if (NISENTRYLEN (0, 0, result) >= room_left)
+@@ -72,39 +72,45 @@ _nss_nisplus_parse_netent (nis_result *r
+            NISENTRYLEN (0, 0, result));
+   first_unused[NISENTRYLEN (0, 0, result)] = '\0';
+   network->n_name = first_unused;
+-  room_left -= (strlen (first_unused) +1);
+-  first_unused += strlen (first_unused) +1;
++  size_t len = strlen (first_unused) + 1;
++  room_left -= len;
++  first_unused += len;
++
+   network->n_addrtype = 0;
+   network->n_net = inet_network (NISENTRYVAL (0, 2, result));
+-  char *p = first_unused;
+-  char *line = p;
+-  for (unsigned int i = 0; i < result->objects.objects_len; ++i)
++  /* XXX Rewrite at some point to allocate the array first and then
++     copy the strings.  It wasteful to first concatenate the strings
++     to just split them again later.  */
++  char *line = first_unused;
++  for (unsigned int i = 0; i < NIS_RES_NUMOBJ (result); ++i)
+     {
+       if (strcmp (NISENTRYVAL (i, 1, result), network->n_name) != 0)
+         {
+           if (NISENTRYLEN (i, 1, result) + 2 > room_left)
+           goto no_more_room;
+-        *p++ = ' ';
+-          p = __stpncpy (p, NISENTRYVAL (i, 1, result),
+-                       NISENTRYLEN (i, 1, result));
+-          *p = '\0';
++        *first_unused++ = ' ';
++          first_unused = __stpncpy (first_unused, NISENTRYVAL (i, 1, result),
++                                  NISENTRYLEN (i, 1, result));
+           room_left -= (NISENTRYLEN (i, 1, result) + 1);
+         }
+     }
+-  *p++ = '\0';
+-  first_unused = p;
++  *first_unused++ = '\0';
+   /* Adjust the pointer so it is aligned for
+      storing pointers.  */
+-  first_unused += __alignof__ (char *) - 1;
+-  first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *));
+-  network->n_aliases = (char **) first_unused;
+-  if (room_left < 2 * sizeof (char *))
++  size_t adjust = ((__alignof__ (char *)
++                  - (first_unused - (char *) 0) % __alignof__ (char *))
++                 % __alignof__ (char *));
++  if (room_left < adjust + sizeof (char *))
+     goto no_more_room;
+-  room_left -= (2 * sizeof (char *));
+-  network->n_aliases[0] = NULL;
++  first_unused += adjust;
++  room_left -= adjust;
++  network->n_aliases = (char **) first_unused;
++
++  /* For the terminating NULL pointer.  */
++  room_left -= sizeof (char *);
+   unsigned int i = 0;
+   while (*line != '\0')
+@@ -120,24 +126,20 @@ _nss_nisplus_parse_netent (nis_result *r
+       goto no_more_room;
+       room_left -= sizeof (char *);
+-      network->n_aliases[i] = line;
++      network->n_aliases[i++] = line;
+       while (*line != '\0' && *line != ' ')
+         ++line;
+       if (*line == ' ')
+-      {
+-        *line = '\0';
+-        ++line;
+-          ++i;
+-        }
+-      else
+-        network->n_aliases[i + 1] = NULL;
++      *line++ = '\0';
+     }
++  network->n_aliases[i] = NULL;
+   return 1;
+ }
++
+ static enum nss_status
+ _nss_create_tablename (int *errnop)
+ {
+@@ -230,6 +232,11 @@ internal_nisplus_getnetent_r (struct net
+           }
+         result = nis_first_entry (tablename_val);
++        if (result == NULL)
++          {
++            *errnop = errno;
++            return NSS_STATUS_TRYAGAIN;
++          }
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           {
+             int retval = niserr2nss (result->status);
+@@ -247,9 +254,13 @@ internal_nisplus_getnetent_r (struct net
+       }
+       else
+       {
+-        nis_result *res = nis_next_entry (tablename_val, &result->cookie);
+         saved_res = result;
+-        result = res;
++        result = nis_next_entry (tablename_val, &result->cookie);
++        if (result == NULL)
++          {
++            *errnop = errno;
++            return NSS_STATUS_TRYAGAIN;
++          }
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           {
+             int retval = niserr2nss (result->status);
+--- libc/nis/nss_nisplus/nisplus-parser.c      24 Oct 2004 21:23:20 -0000      1.11
++++ libc/nis/nss_nisplus/nisplus-parser.c      30 Apr 2006 07:00:12 -0000      1.16
+@@ -25,33 +25,37 @@
+ #include "nisplus-parser.h"
+-#define NISENTRYVAL(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
++#define NISENTRYVAL(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+-#define NISENTRYLEN(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
++#define NISENTRYLEN(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
+ int
+-_nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw,
++_nss_nisplus_parse_pwent_chk (nis_result *result, struct passwd *pw,
++                            char *buffer, size_t buflen, int *errnop)
++{
++  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
++      || NIS_RES_NUMOBJ (result) != 1
++      || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
++      || strcmp (NIS_RES_OBJECT (result)->EN_data.en_type, "passwd_tbl") != 0
++      || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 7)
++    return 0;
++
++  return _nss_nisplus_parse_pwent (result, 0, pw, buffer, buflen, errnop);
++}
++
++
++int
++_nss_nisplus_parse_pwent (nis_result *result, size_t entry, struct passwd *pw,
+                         char *buffer, size_t buflen, int *errnop)
+ {
+   char *first_unused = buffer;
+   size_t room_left = buflen;
+   size_t len;
+-  if (result == NULL)
+-    return 0;
+-
+-  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+-      || result->objects.objects_len != 1
+-      || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
+-      || strcmp (result->objects.objects_val->EN_data.en_type,
+-               "passwd_tbl") != 0
+-      || result->objects.objects_val->EN_data.en_cols.en_cols_len < 7)
+-    return 0;
+-
+-  if (NISENTRYLEN (0, 0, result) >= room_left)
++  if (NISENTRYLEN (entry, 0, result) >= room_left)
+     {
+       /* The line is too long for our buffer.  */
+     no_more_room:
+@@ -59,89 +63,95 @@ _nss_nisplus_parse_pwent (nis_result *re
+       return -1;
+     }
+-  strncpy (first_unused, NISENTRYVAL (0, 0, result),
+-         NISENTRYLEN (0, 0, result));
+-  first_unused[NISENTRYLEN (0, 0, result)] = '\0';
++  strncpy (first_unused, NISENTRYVAL (entry, 0, result),
++         NISENTRYLEN (entry, 0, result));
++  first_unused[NISENTRYLEN (entry, 0, result)] = '\0';
+   len = strlen (first_unused);
+   if (len == 0) /* No name ? Should never happen, database is corrupt */
+     return 0;
+   pw->pw_name = first_unused;
+-  room_left -= (len + 1);
+-  first_unused += (len + 1);
++  room_left -= len + 1;
++  first_unused += len + 1;
+-  if (NISENTRYLEN (0, 1, result) >= room_left)
++  if (NISENTRYLEN (entry, 1, result) >= room_left)
+     goto no_more_room;
+-  strncpy (first_unused, NISENTRYVAL (0, 1, result),
+-         NISENTRYLEN (0, 1, result));
+-  first_unused[NISENTRYLEN (0, 1, result)] = '\0';
++  strncpy (first_unused, NISENTRYVAL (entry, 1, result),
++         NISENTRYLEN (entry, 1, result));
++  first_unused[NISENTRYLEN (entry, 1, result)] = '\0';
+   pw->pw_passwd = first_unused;
+   len = strlen (first_unused);
+-  room_left -= (len + 1);
+-  first_unused += (len + 1);
++  room_left -= len + 1;
++  first_unused += len + 1;
+-  if (NISENTRYLEN(0, 2, result) >= room_left)
+-    goto no_more_room;
++  char *numstr = NISENTRYVAL (entry, 2, result);
++  len = NISENTRYLEN (entry, 2, result);
++  if (len == 0 && numstr[len - 1] != '\0')
++    {
++      if (len >= room_left)
++      goto no_more_room;
+-  strncpy (first_unused, NISENTRYVAL (0, 2, result),
+-         NISENTRYLEN (0, 2, result));
+-  first_unused[NISENTRYLEN (0, 2, result)] = '\0';
+-  len = strlen (first_unused);
+-  if (len == 0) /* If we don't have a uid, it's an invalid shadow entry */
++      strncpy (first_unused, numstr, len);
++      first_unused[len] = '\0';
++      numstr = first_unused;
++    }
++  if (numstr[0] == '\0')
++    /* If we don't have a uid, it's an invalid shadow entry.  */
+     return 0;
+-  pw->pw_uid = strtoul (first_unused, NULL, 10);
+-  room_left -= (len + 1);
+-  first_unused += (len + 1);
++  pw->pw_uid = strtoul (numstr, NULL, 10);
+-  if (NISENTRYLEN (0, 3, result) >= room_left)
+-    goto no_more_room;
++  numstr = NISENTRYVAL (entry, 3, result);
++  len = NISENTRYLEN (entry, 3, result);
++  if (len == 0 && numstr[len - 1] != '\0')
++    {
++      if (len >= room_left)
++      goto no_more_room;
+-  strncpy (first_unused, NISENTRYVAL (0, 3, result),
+-         NISENTRYLEN (0, 3, result));
+-  first_unused[NISENTRYLEN (0, 3, result)] = '\0';
+-  len = strlen (first_unused);
+-  if (len == 0) /* If we don't have a gid, it's an invalid shadow entry */
++      strncpy (first_unused, numstr, len);
++      first_unused[len] = '\0';
++      numstr = first_unused;
++    }
++  if (numstr[0] == '\0')
++    /* If we don't have a gid, it's an invalid shadow entry.  */
+     return 0;
+-  pw->pw_gid = strtoul (first_unused, NULL, 10);
+-  room_left -= (len + 1);
+-  first_unused += (len + 1);
++  pw->pw_gid = strtoul (numstr, NULL, 10);
+-  if (NISENTRYLEN(0, 4, result) >= room_left)
++  if (NISENTRYLEN(entry, 4, result) >= room_left)
+     goto no_more_room;
+-  strncpy (first_unused, NISENTRYVAL (0, 4, result),
+-         NISENTRYLEN (0, 4, result));
+-  first_unused[NISENTRYLEN (0, 4, result)] = '\0';
++  strncpy (first_unused, NISENTRYVAL (entry, 4, result),
++         NISENTRYLEN (entry, 4, result));
++  first_unused[NISENTRYLEN (entry, 4, result)] = '\0';
+   pw->pw_gecos = first_unused;
+   len = strlen (first_unused);
+-  room_left -= (len + 1);
+-  first_unused += (len + 1);
++  room_left -= len + 1;
++  first_unused += len + 1;
+-  if (NISENTRYLEN (0, 5, result) >= room_left)
++  if (NISENTRYLEN (entry, 5, result) >= room_left)
+     goto no_more_room;
+-  strncpy (first_unused, NISENTRYVAL (0, 5, result),
+-         NISENTRYLEN (0, 5, result));
+-  first_unused[NISENTRYLEN (0, 5, result)] = '\0';
++  strncpy (first_unused, NISENTRYVAL (entry, 5, result),
++         NISENTRYLEN (entry, 5, result));
++  first_unused[NISENTRYLEN (entry, 5, result)] = '\0';
+   pw->pw_dir = first_unused;
+   len = strlen (first_unused);
+-  room_left -= (len + 1);
+-  first_unused += (len + 1);
++  room_left -= len + 1;
++  first_unused += len + 1;
+-  if (NISENTRYLEN (0, 6, result) >= room_left)
++  if (NISENTRYLEN (entry, 6, result) >= room_left)
+     goto no_more_room;
+-  strncpy (first_unused, NISENTRYVAL (0, 6, result),
+-         NISENTRYLEN (0, 6, result));
+-  first_unused[NISENTRYLEN (0, 6, result)] = '\0';
++  strncpy (first_unused, NISENTRYVAL (entry, 6, result),
++         NISENTRYLEN (entry, 6, result));
++  first_unused[NISENTRYLEN (entry, 6, result)] = '\0';
+   pw->pw_shell = first_unused;
+   len = strlen (first_unused);
+-  room_left -= (len + 1);
+-  first_unused += (len + 1);
++  room_left -= len + 1;
++  first_unused += len + 1;
+   return 1;
+ }
+-libnss_nisplus_hidden_def (_nss_nisplus_parse_pwent)
++
+ int
+ _nss_nisplus_parse_grent (nis_result *result, u_long entry, struct group *gr,
+@@ -157,10 +167,10 @@ _nss_nisplus_parse_grent (nis_result *re
+     return 0;
+   if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+-      || __type_of(result->objects.objects_val) != NIS_ENTRY_OBJ
+-      || strcmp (result->objects.objects_val[entry].EN_data.en_type,
++      || __type_of(NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
++      || strcmp (NIS_RES_OBJECT (result)[entry].EN_data.en_type,
+                "group_tbl") != 0
+-      || result->objects.objects_val[entry].EN_data.en_cols.en_cols_len < 4)
++      || NIS_RES_OBJECT (result)[entry].EN_data.en_cols.en_cols_len < 4)
+     return 0;
+   if (NISENTRYLEN (entry, 0, result) >= room_left)
+@@ -178,8 +188,8 @@ _nss_nisplus_parse_grent (nis_result *re
+   if (len == 0) /* group table is corrupt */
+     return 0;
+   gr->gr_name = first_unused;
+-  room_left -= (len + 1);
+-  first_unused += (len + 1);
++  room_left -= len + 1;
++  first_unused += len + 1;
+   if (NISENTRYLEN (entry, 1, result) >= room_left)
+     goto no_more_room;
+@@ -189,21 +199,24 @@ _nss_nisplus_parse_grent (nis_result *re
+   first_unused[NISENTRYLEN (entry, 1, result)] = '\0';
+   gr->gr_passwd = first_unused;
+   len = strlen (first_unused);
+-  room_left -= (len + 1);
+-  first_unused += (len + 1);
++  room_left -= len + 1;
++  first_unused += len + 1;
+-  if (NISENTRYLEN (entry, 2, result) >= room_left)
+-    goto no_more_room;
++  char *numstr = NISENTRYVAL (entry, 2, result);
++  len = NISENTRYLEN (entry, 2, result);
++  if (len == 0 && numstr[len - 1] != '\0')
++    {
++      if (len >= room_left)
++      goto no_more_room;
+-  strncpy (first_unused, NISENTRYVAL (entry, 2, result),
+-         NISENTRYLEN (entry, 2, result));
+-  first_unused[NISENTRYLEN (entry, 2, result)] = '\0';
+-  len = strlen (first_unused);
+-  if (len == 0) /* We should always have an gid */
++      strncpy (first_unused, numstr, len);
++      first_unused[len] = '\0';
++      numstr = first_unused;
++    }
++  if (numstr[0] == '\0')
++    /* We should always have a gid.  */
+     return 0;
+-  gr->gr_gid = strtoul (first_unused, NULL, 10);
+-  room_left -= (strlen (first_unused) + 1);
+-  first_unused += strlen (first_unused) + 1;
++  gr->gr_gid = strtoul (numstr, NULL, 10);
+   if (NISENTRYLEN (entry, 3, result) >= room_left)
+     goto no_more_room;
+@@ -213,12 +226,17 @@ _nss_nisplus_parse_grent (nis_result *re
+   first_unused[NISENTRYLEN (entry, 3, result)] = '\0';
+   line = first_unused;
+   len = strlen (line);
+-  room_left -= (len + 1);
+-  first_unused += (len + 1);
++  room_left -= len + 1;
++  first_unused += len + 1;
+   /* Adjust the pointer so it is aligned for
+      storing pointers.  */
+-  first_unused += __alignof__ (char *) - 1;
+-  first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *));
++  size_t adjust = ((__alignof__ (char *)
++                  - (first_unused - (char *) 0) % __alignof__ (char *))
++                 % __alignof__ (char *));
++  if (room_left < adjust)
++    goto no_more_room;
++  first_unused += adjust;
++  room_left -= adjust;
+   gr->gr_mem = (char **) first_unused;
+   count = 0;
+@@ -243,12 +261,10 @@ _nss_nisplus_parse_grent (nis_result *re
+       {
+         int is = isspace (*line);
+-        *line = '\0';
++        *line++ = '\0';
+         if (is)
+           while (*line != '\0' && (*line == ',' || isspace (*line)))
+             ++line;
+-        else
+-          ++line;
+       }
+     }
+   if (room_left < sizeof (char *))
+@@ -258,7 +274,7 @@ _nss_nisplus_parse_grent (nis_result *re
+   return 1;
+ }
+-libnss_nisplus_hidden_def (_nss_nisplus_parse_grent)
++
+ int
+ _nss_nisplus_parse_spent (nis_result *result, struct spwd *sp,
+@@ -272,11 +288,10 @@ _nss_nisplus_parse_spent (nis_result *re
+     return 0;
+   if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+-      || result->objects.objects_len != 1
+-      || __type_of(result->objects.objects_val) != NIS_ENTRY_OBJ
+-      || strcmp (result->objects.objects_val->EN_data.en_type,
+-               "passwd_tbl") != 0
+-      || result->objects.objects_val[0].EN_data.en_cols.en_cols_len < 8)
++      || NIS_RES_NUMOBJ (result) != 1
++      || __type_of(NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
++      || strcmp (NIS_RES_OBJECT (result)->EN_data.en_type, "passwd_tbl") != 0
++      || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 8)
+     return 0;
+   if (NISENTRYLEN (0, 0, result) >= room_left)
+@@ -294,8 +309,8 @@ _nss_nisplus_parse_spent (nis_result *re
+   if (len == 0)
+     return 0;
+   sp->sp_namp = first_unused;
+-  room_left -= (len + 1);
+-  first_unused += (len + 1);
++  room_left -= len + 1;
++  first_unused += len + 1;
+   if (NISENTRYLEN (0, 1, result) >= room_left)
+     goto no_more_room;
+@@ -305,8 +320,8 @@ _nss_nisplus_parse_spent (nis_result *re
+   first_unused[NISENTRYLEN (0, 1, result)] = '\0';
+   sp->sp_pwdp = first_unused;
+   len = strlen (first_unused);
+-  room_left -= (len + 1);
+-  first_unused += (len + 1);
++  room_left -= len + 1;
++  first_unused += len + 1;
+   sp->sp_lstchg = sp->sp_min = sp->sp_max = sp->sp_warn = sp->sp_inact =
+     sp->sp_expire = -1;
+@@ -314,10 +329,8 @@ _nss_nisplus_parse_spent (nis_result *re
+   if (NISENTRYLEN (0, 7, result) > 0)
+     {
+-      char *line, *cp;
+-
+-      line = NISENTRYVAL (0, 7, result);
+-      cp = strchr (line, ':');
++      char *line = NISENTRYVAL (0, 7, result);
++      char *cp = strchr (line, ':');
+       if (cp == NULL)
+       return 1;
+       *cp++ = '\0';
+@@ -373,4 +386,3 @@ _nss_nisplus_parse_spent (nis_result *re
+   return 1;
+ }
+-libnss_nisplus_hidden_def (_nss_nisplus_parse_spent)
+--- libc/nis/nss_nisplus/nisplus-proto.c       25 Mar 2006 20:59:19 -0000      1.21
++++ libc/nis/nss_nisplus/nisplus-proto.c       30 Apr 2006 05:44:23 -0000      1.25
+@@ -35,20 +35,20 @@ static nis_result *result;
+ static nis_name tablename_val;
+ static u_long tablename_len;
+-#define NISENTRYVAL(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
++#define NISENTRYVAL(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
++
++#define NISENTRYLEN(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
+-#define NISENTRYLEN(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
+ static int
+-_nss_nisplus_parse_protoent (nis_result * result, struct protoent *proto,
++_nss_nisplus_parse_protoent (nis_result *result, struct protoent *proto,
+                            char *buffer, size_t buflen, int *errnop)
+ {
+   char *first_unused = buffer;
+   size_t room_left = buflen;
+   unsigned int i;
+-  char *p, *line;
+   if (result == NULL)
+     return 0;
+@@ -71,41 +71,44 @@ _nss_nisplus_parse_protoent (nis_result 
+            NISENTRYLEN (0, 0, result));
+   first_unused[NISENTRYLEN (0, 0, result)] = '\0';
+   proto->p_name = first_unused;
+-  room_left -= (strlen (first_unused) +1);
+-  first_unused += strlen (first_unused) +1;
++  size_t len = strlen (first_unused) + 1;
++  room_left -= len;
++  first_unused += len;
+-  if (NISENTRYLEN (0, 2, result) + 1 > room_left)
+-    goto no_more_room;
+   proto->p_proto = atoi (NISENTRYVAL (0, 2, result));
+-  p = first_unused;
+-  line = p;
+-  for (i = 0; i < result->objects.objects_len; ++i)
++  /* XXX Rewrite at some point to allocate the array first and then
++     copy the strings.  It wasteful to first concatenate the strings
++     to just split them again later.  */
++  char *line = first_unused;
++  for (i = 0; i < NIS_RES_NUMOBJ (result); ++i)
+     {
+       if (strcmp (NISENTRYVAL (i, 1, result), proto->p_name) != 0)
+         {
+           if (NISENTRYLEN (i, 1, result) + 2 > room_left)
+             goto no_more_room;
+-        *p++ = ' ';
+-          p = __stpncpy (p, NISENTRYVAL (i, 1, result),
+-                       NISENTRYLEN (i, 1, result));
+-          *p = '\0';
+-          room_left -= (NISENTRYLEN (i, 1, result) + 1);
++        *first_unused++ = ' ';
++          first_unused = __stpncpy (first_unused, NISENTRYVAL (i, 1, result),
++                                  NISENTRYLEN (i, 1, result));
++          room_left -= NISENTRYLEN (i, 1, result) + 1;
+         }
+     }
+-  *p++ = '\0';
+-  first_unused = p;
++  *first_unused++ = '\0';
+   /* Adjust the pointer so it is aligned for
+      storing pointers.  */
+-  first_unused += __alignof__ (char *) - 1;
+-  first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *));
+-  proto->p_aliases = (char **) first_unused;
+-  if (room_left < sizeof (char *))
++  size_t adjust = ((__alignof__ (char *)
++                  - (first_unused - (char *) 0) % __alignof__ (char *))
++                 % __alignof__ (char *));
++  if (room_left < adjust + sizeof (char *))
+     goto no_more_room;
++  first_unused += adjust;
++  room_left -= adjust;
++  proto->p_aliases = (char **) first_unused;
++
++  /* For the terminating NULL pointer.  */
+   room_left -= sizeof (char *);
+-  proto->p_aliases[0] = NULL;
+   i = 0;
+   while (*line != '\0')
+@@ -120,20 +123,15 @@ _nss_nisplus_parse_protoent (nis_result 
+         goto no_more_room;
+       room_left -= sizeof (char *);
+-      proto->p_aliases[i] = line;
++      proto->p_aliases[i++] = line;
+       while (*line != '\0' && *line != ' ')
+         ++line;
+       if (*line == ' ')
+-        {
+-          *line = '\0';
+-          ++line;
+-          ++i;
+-        }
+-      else
+-        proto->p_aliases[i+1] = NULL;
++      *line++ = '\0';
+     }
++  proto->p_aliases[i] = NULL;
+   return 1;
+ }
+@@ -229,6 +227,11 @@ internal_nisplus_getprotoent_r (struct p
+           }
+         result = nis_first_entry (tablename_val);
++        if (result == NULL)
++          {
++            *errnop = errno;
++            return NSS_STATUS_TRYAGAIN;
++          }
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           return niserr2nss (result->status);
+       }
+@@ -236,7 +239,11 @@ internal_nisplus_getprotoent_r (struct p
+       {
+         saved_res = result;
+         result = nis_next_entry (tablename_val, &result->cookie);
+-
++        if (result == NULL)
++          {
++            *errnop = errno;
++            return NSS_STATUS_TRYAGAIN;
++          }
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           {
+             nis_freeresult (saved_res);
+--- libc/nis/nss_nisplus/nisplus-publickey.c   7 Apr 2006 00:11:09 -0000       1.18
++++ libc/nis/nss_nisplus/nisplus-publickey.c   30 Apr 2006 15:35:10 -0000      1.20
+@@ -91,20 +91,20 @@ _nss_nisplus_getpublickey (const char *n
+       return retval;
+     }
+-  if (res->objects.objects_len > 1)
++  if (NIS_RES_NUMOBJ (res) > 1)
+     {
+       /*
+        * More than one principal with same uid?
+        * something wrong with cred table. Should be unique
+        * Warn user and continue.
+        */
+-      printf (_("DES entry for netname %s not unique\n"), netname);
++      syslog (LOG_ERR, _("DES entry for netname %s not unique\n"), netname);
+       nis_freeresult (res);
+       return NSS_STATUS_SUCCESS;
+     }
+-  len = ENTRY_LEN (res->objects.objects_val, 3);
+-  memcpy (pkey, ENTRY_VAL (res->objects.objects_val,3), len);
++  len = ENTRY_LEN (NIS_RES_OBJECT (res), 3);
++  memcpy (pkey, ENTRY_VAL (NIS_RES_OBJECT (res),3), len);
+   pkey[len] = 0;
+   cptr = strchr (pkey, ':');
+   if (cptr)
+@@ -114,6 +114,7 @@ _nss_nisplus_getpublickey (const char *n
+   return NSS_STATUS_SUCCESS;
+ }
++
+ enum nss_status
+ _nss_nisplus_getsecretkey (const char *netname, char *skey, char *passwd,
+                          int *errnop)
+@@ -172,20 +173,20 @@ _nss_nisplus_getsecretkey (const char *n
+       return retval;
+     }
+-  if (res->objects.objects_len > 1)
++  if (NIS_RES_NUMOBJ (res) > 1)
+     {
+       /*
+        * More than one principal with same uid?
+        * something wrong with cred table. Should be unique
+        * Warn user and continue.
+        */
+-      printf (_("DES entry for netname %s not unique\n"), netname);
++      syslog (LOG_ERR, _("DES entry for netname %s not unique\n"), netname);
+       nis_freeresult (res);
+       return NSS_STATUS_SUCCESS;
+     }
+-  len = ENTRY_LEN (res->objects.objects_val, 4);
+-  memcpy (buf, ENTRY_VAL (res->objects.objects_val,4), len);
++  len = ENTRY_LEN (NIS_RES_OBJECT (res), 4);
++  memcpy (buf, ENTRY_VAL (NIS_RES_OBJECT (res), 4), len);
+   buf[len] = '\0';
+   cptr = strchr (buf, ':');
+   if (cptr)
+@@ -204,6 +205,7 @@ _nss_nisplus_getsecretkey (const char *n
+   return NSS_STATUS_SUCCESS;
+ }
++
+ /* Parse information from the passed string.
+    The format of the string passed is gid,grp,grp, ...  */
+ static enum nss_status
+@@ -224,8 +226,12 @@ parse_grp_str (const char *s, gid_t *gid
+   gidlen = 0;
+   /* After strtoul() ep should point to the marker ',', which means
+-     here starts a new value. */
+-  while (ep != NULL && *ep == ',')
++     here starts a new value.
++
++     The Sun man pages show that GIDLIST should contain at least NGRPS
++     elements.  Limiting the number written by this value is the best
++     we can do.  */
++  while (ep != NULL && *ep == ',' && gidlen < NGRPS)
+     {
+       ep++;
+       s = ep;
+@@ -305,7 +311,7 @@ _nss_nisplus_netname2user (char netname[
+       return NSS_STATUS_UNAVAIL;
+     }
+-  if (res->objects.objects_len > 1)
++  if (NIS_RES_NUMOBJ (res) > 1)
+     /*
+      * A netname belonging to more than one principal?
+      * Something wrong with cred table. should be unique.
+@@ -315,8 +321,8 @@ _nss_nisplus_netname2user (char netname[
+           _("netname2user: DES entry for %s in directory %s not unique"),
+           netname, domain);
+-  len = ENTRY_LEN (res->objects.objects_val, 0);
+-  strncpy (principal, ENTRY_VAL (res->objects.objects_val, 0), len);
++  len = ENTRY_LEN (NIS_RES_OBJECT (res), 0);
++  strncpy (principal, ENTRY_VAL (NIS_RES_OBJECT (res), 0), len);
+   principal[len] = '\0';
+   nis_freeresult (res);
+@@ -328,7 +334,7 @@ _nss_nisplus_netname2user (char netname[
+    *     LOCAL entry in **local** cred table.
+    */
+   domain = nis_local_directory ();
+-  if ((strlen (principal) + strlen (domain) + 45) > (size_t) NIS_MAXNAMELEN)
++  if (strlen (principal) + strlen (domain) + 45 > (size_t) NIS_MAXNAMELEN)
+     {
+       syslog (LOG_ERR, _("netname2user: principal name `%s' too long"),
+             principal);
+@@ -379,7 +385,7 @@ _nss_nisplus_netname2user (char netname[
+       return NSS_STATUS_UNAVAIL;
+     }
+-  if (res->objects.objects_len > 1)
++  if (NIS_RES_NUMOBJ (res) > 1)
+     /*
+      * A principal can have more than one LOCAL entry?
+      * Something wrong with cred table.
+@@ -389,7 +395,7 @@ _nss_nisplus_netname2user (char netname[
+           _("netname2user: LOCAL entry for %s in directory %s not unique"),
+           netname, domain);
+   /* Fetch the uid */
+-  *uidp = strtoul (ENTRY_VAL (res->objects.objects_val, 2), NULL, 10);
++  *uidp = strtoul (ENTRY_VAL (NIS_RES_OBJECT (res), 2), NULL, 10);
+   if (*uidp == 0)
+     {
+@@ -398,7 +404,7 @@ _nss_nisplus_netname2user (char netname[
+       return NSS_STATUS_NOTFOUND;
+     }
+-  parse_grp_str (ENTRY_VAL (res->objects.objects_val, 3),
++  parse_grp_str (ENTRY_VAL (NIS_RES_OBJECT (res), 3),
+                gidp, gidlenp, gidlist, errnop);
+   nis_freeresult (res);
+--- libc/nis/nss_nisplus/nisplus-pwd.c 25 Mar 2006 20:59:19 -0000      1.21
++++ libc/nis/nss_nisplus/nisplus-pwd.c 29 Apr 2006 20:19:09 -0000      1.22
+@@ -28,10 +28,18 @@
+ #include "nss-nisplus.h"
+ #include "nisplus-parser.h"
++#include <libnsl.h>
++
+ __libc_lock_define_initialized (static, lock)
++/* Previous result of iteration.  */
+ static nis_result *result;
++
++/* All results of batch table load.  */
++static nis_result *cached_results;
++static size_t cached_results_iter;
++
+ nis_name pwd_tablename_val attribute_hidden;
+ size_t pwd_tablename_len attribute_hidden;
+@@ -69,95 +77,195 @@ _nss_pwd_create_tablename (int *errnop)
+ }
+-enum nss_status
+-_nss_nisplus_setpwent (int stayopen)
++static void
++internal_nisplus_endpwent (void)
+ {
+-  enum nss_status status = NSS_STATUS_SUCCESS;
+-
+-  __libc_lock_lock (lock);
++  if (cached_results != NULL)
++    {
++      nis_freeresult (cached_results);
++      cached_results = NULL;
++      cached_results_iter = 0;
++    }
+   if (result != NULL)
+     {
+       nis_freeresult (result);
+       result = NULL;
+     }
++}
++
++
++static enum nss_status
++internal_nisplus_setpwent (int *errnop)
++{
++  enum nss_status status;
++
++  cached_results = nis_list (pwd_tablename_val, FOLLOW_PATH | FOLLOW_LINKS,
++                           NULL, NULL);
++
++  if (cached_results == NULL)
++    {
++      *errnop = errno;
++      status = NSS_STATUS_TRYAGAIN;
++    }
++  else if (__builtin_expect ((status = niserr2nss (cached_results->status))
++                           != NSS_STATUS_SUCCESS, 0))
++    {
++      nis_freeresult (cached_results);
++      cached_results = NULL;
++    }
++  else if (__builtin_expect (__type_of (NIS_RES_OBJECT (cached_results))
++                           != NIS_ENTRY_OBJ
++                           || strcmp (NIS_RES_OBJECT (cached_results)->EN_data.en_type,
++                                      "passwd_tbl") != 0
++                           || NIS_RES_OBJECT (cached_results)->EN_data.en_cols.en_cols_len < 7,
++                           0))
++    {
++      nis_freeresult (cached_results);
++      cached_results = NULL;
++      status = NSS_STATUS_NOTFOUND;
++    }
++
++  return status;
++}
++
++
++enum nss_status
++_nss_nisplus_setpwent (int stayopen)
++{
++  enum nss_status status = NSS_STATUS_SUCCESS;
++
++  __libc_lock_lock (lock);
++
++  internal_nisplus_endpwent ();
+   if (pwd_tablename_val == NULL)
+     {
++      // XXX We need to be able to set errno.  Pass in new parameter.
+       int err;
+       status = _nss_pwd_create_tablename (&err);
+     }
++  if (status == NSS_STATUS_SUCCESS
++      && (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ))
++    {
++      // XXX We need to be able to set errno.  Pass in new parameter.
++      int err;
++      status = internal_nisplus_setpwent (&err);
++    }
++
+   __libc_lock_unlock (lock);
+   return status;
+ }
++
+ enum nss_status
+ _nss_nisplus_endpwent (void)
+ {
+   __libc_lock_lock (lock);
+-  if (result != NULL)
+-    {
+-      nis_freeresult (result);
+-      result = NULL;
+-    }
++  internal_nisplus_endpwent ();
+   __libc_lock_unlock (lock);
+   return NSS_STATUS_SUCCESS;
+ }
++
+ static enum nss_status
+ internal_nisplus_getpwent_r (struct passwd *pw, char *buffer, size_t buflen,
+                            int *errnop)
+ {
+-  int parse_res;
++  int parse_res = -1;
++  nis_result *saved_res = NULL;
+   /* Get the next entry until we found a correct one. */
+   do
+     {
+-      nis_result *saved_res;
+-
+-      if (result == NULL)
++      if (cached_results != NULL)
+       {
+-        saved_res = NULL;
+-          if (pwd_tablename_val == NULL)
+-          {
+-            enum nss_status status = _nss_pwd_create_tablename (errnop);
+-
+-            if (status != NSS_STATUS_SUCCESS)
+-              return status;
+-          }
+-
+-        result = nis_first_entry (pwd_tablename_val);
+-        if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+-          return niserr2nss (result->status);
++      handle_batch_read:
++        /* See whether we reported the last problem.  */
++        if (cached_results_iter >= NIS_RES_NUMOBJ (cached_results))
++          return NSS_STATUS_NOTFOUND;
++
++        parse_res = _nss_nisplus_parse_pwent (cached_results,
++                                              cached_results_iter, pw,
++                                              buffer, buflen, errnop);
+       }
+       else
+       {
+-        saved_res = result;
+-        result = nis_next_entry (pwd_tablename_val, &result->cookie);
+-        if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
++        if (result == NULL)
++          {
++            if (pwd_tablename_val == NULL)
++              {
++                enum nss_status status = _nss_pwd_create_tablename (errnop);
++
++                if (status != NSS_STATUS_SUCCESS)
++                  return status;
++              }
++
++            /* Determine whether we should instead read all entries at
++               once.  */
++            if (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
++              {
++                enum nss_status status = internal_nisplus_setpwent (errnop);
++
++                if (status == NSS_STATUS_SUCCESS && cached_results != NULL)
++                  goto handle_batch_read;
++              }
++
++            saved_res = NULL;
++
++            result = nis_first_entry (pwd_tablename_val);
++            if (result == NULL)
++              {
++                *errnop = errno;
++                return NSS_STATUS_TRYAGAIN;
++              }
++            if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
++              return niserr2nss (result->status);
++          }
++        else
+           {
+-            nis_freeresult (saved_res);
+-            return niserr2nss (result->status);
++            saved_res = result;
++            result = nis_next_entry (pwd_tablename_val, &result->cookie);
++            if (result == NULL)
++              {
++                *errnop = errno;
++                return NSS_STATUS_TRYAGAIN;
++              }
++            if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
++              {
++                nis_freeresult (saved_res);
++                return niserr2nss (result->status);
++              }
+           }
++
++        parse_res = _nss_nisplus_parse_pwent_chk (result, pw, buffer,
++                                                  buflen, errnop);
+       }
+-      parse_res = _nss_nisplus_parse_pwent (result, pw, buffer,
+-                                          buflen, errnop);
+       if (__builtin_expect (parse_res == -1, 0))
+       {
+-        nis_freeresult (result);
+-        result = saved_res;
++        if (cached_results == NULL)
++          {
++            nis_freeresult (result);
++            result = saved_res;
++          }
+         *errnop = ERANGE;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      if (saved_res)
+-      nis_freeresult (saved_res);
++      if (cached_results != NULL)
++      ++cached_results_iter;
++      else
++      if (saved_res)
++        {
++          nis_freeresult (saved_res);
++          saved_res = NULL;
++        }
+     }
+   while (!parse_res);
+@@ -223,7 +331,8 @@ _nss_nisplus_getpwnam_r (const char *nam
+       return status;
+     }
+-  parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop);
++  parse_res = _nss_nisplus_parse_pwent_chk (result, pw, buffer, buflen,
++                                          errnop);
+   nis_freeresult (result);
+@@ -282,7 +391,8 @@ _nss_nisplus_getpwuid_r (const uid_t uid
+       return status;
+     }
+-  parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop);
++  parse_res = _nss_nisplus_parse_pwent_chk (result, pw, buffer, buflen,
++                                          errnop);
+   nis_freeresult (result);
+--- libc/nis/nss_nisplus/nisplus-rpc.c 25 Mar 2006 20:59:19 -0000      1.21
++++ libc/nis/nss_nisplus/nisplus-rpc.c 30 Apr 2006 05:44:23 -0000      1.23
+@@ -35,11 +35,12 @@ static nis_result *result;
+ static nis_name tablename_val;
+ static u_long tablename_len;
+-#define NISENTRYVAL(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
++#define NISENTRYVAL(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
++
++#define NISENTRYLEN(idx, col, res) \
++        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
+-#define NISENTRYLEN(idx,col,res) \
+-        ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
+ static int
+ _nss_nisplus_parse_rpcent (nis_result *result, struct rpcent *rpc,
+@@ -48,17 +49,16 @@ _nss_nisplus_parse_rpcent (nis_result *r
+   char *first_unused = buffer;
+   size_t room_left = buflen;
+   unsigned int i;
+-  char *p, *line;
++  char *line;
+   if (result == NULL)
+     return 0;
+   if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+-      || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
+-      || strcmp (result->objects.objects_val[0].EN_data.en_type,
+-               "rpc_tbl") != 0
+-      || result->objects.objects_val[0].EN_data.en_cols.en_cols_len < 3)
++      || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
++      || strcmp (NIS_RES_OBJECT (result)[0].EN_data.en_type, "rpc_tbl") != 0
++      || NIS_RES_OBJECT (result)[0].EN_data.en_cols.en_cols_len < 3)
+     return 0;
+   if (NISENTRYLEN (0, 0, result) >= room_left)
+@@ -71,37 +71,43 @@ _nss_nisplus_parse_rpcent (nis_result *r
+            NISENTRYLEN (0, 0, result));
+   first_unused[NISENTRYLEN (0, 0, result)] = '\0';
+   rpc->r_name = first_unused;
+-  room_left -= (strlen (first_unused) + 1);
+-  first_unused += strlen (first_unused) + 1;
++  size_t len = strlen (first_unused) + 1;
++  room_left -= len;
++  first_unused += len;
++
+   rpc->r_number = atoi (NISENTRYVAL (0, 2, result));
+-  p = first_unused;
+-  line = p;
+-  for (i = 0; i < result->objects.objects_len; ++i)
++  /* XXX Rewrite at some point to allocate the array first and then
++     copy the strings.  It wasteful to first concatenate the strings
++     to just split them again later.  */
++  line = first_unused;
++  for (i = 0; i < NIS_RES_NUMOBJ (result); ++i)
+     {
+       if (strcmp (NISENTRYVAL (i, 1, result), rpc->r_name) != 0)
+         {
+           if (NISENTRYLEN (i, 1, result) + 2 > room_left)
+           goto no_more_room;
+-        *p++ = ' ';
+-          p = __stpncpy (p, NISENTRYVAL (i, 1, result),
+-                       NISENTRYLEN (i, 1, result));
+-          *p = '\0';
+-          room_left -= (NISENTRYLEN (i, 1, result) + 1);
++        *first_unused++ = ' ';
++          first_unused = __stpncpy (first_unused, NISENTRYVAL (i, 1, result),
++                                  NISENTRYLEN (i, 1, result));
++          room_left -= NISENTRYLEN (i, 1, result) + 1;
+         }
+     }
+-  ++p;
+-  first_unused = p;
++  *first_unused++ = '\0';
+   /* Adjust the pointer so it is aligned for
+      storing pointers.  */
+-  first_unused += __alignof__ (char *) - 1;
+-  first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *));
+-  rpc->r_aliases = (char **) first_unused;
+-  if (room_left < sizeof (char *))
++  size_t adjust = ((__alignof__ (char *)
++                  - (first_unused - (char *) 0) % __alignof__ (char *))
++                 % __alignof__ (char *));
++  if (room_left < adjust + sizeof (char *))
+     goto no_more_room;
++  first_unused += adjust;
++  room_left -= adjust;
++  rpc->r_aliases = (char **) first_unused;
++
++  /* For the terminating NULL pointer.  */
+   room_left -= sizeof (char *);
+-  rpc->r_aliases[0] = NULL;
+   i = 0;
+   while (*line != '\0')
+@@ -117,24 +123,20 @@ _nss_nisplus_parse_rpcent (nis_result *r
+       goto no_more_room;
+       room_left -= sizeof (char *);
+-      rpc->r_aliases[i] = line;
++      rpc->r_aliases[i++] = line;
+       while (*line != '\0' && *line != ' ')
+         ++line;
+       if (*line == ' ')
+-        {
+-        *line = '\0';
+-        ++line;
+-          ++i;
+-        }
+-      else
+-        rpc->r_aliases[i+1] = NULL;
++      *line++ = '\0';
+     }
++  rpc->r_aliases[i] = NULL;
+   return 1;
+ }
++
+ static enum nss_status
+ _nss_create_tablename (int *errnop)
+ {
+@@ -227,6 +229,11 @@ internal_nisplus_getrpcent_r (struct rpc
+           }
+         result = nis_first_entry (tablename_val);
++        if (result == NULL)
++          {
++            *errnop = errno;
++            return NSS_STATUS_TRYAGAIN;
++          }
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           return niserr2nss (result->status);
+       }
+@@ -234,6 +241,11 @@ internal_nisplus_getrpcent_r (struct rpc
+       {
+         saved_res = result;
+         result = nis_next_entry (tablename_val, &result->cookie);
++        if (result == NULL)
++          {
++            *errnop = errno;
++            return NSS_STATUS_TRYAGAIN;
++          }
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           {
+             nis_freeresult (saved_res);
+--- libc/nis/nss_nisplus/nisplus-service.c     25 Mar 2006 20:59:19 -0000      1.23
++++ libc/nis/nss_nisplus/nisplus-service.c     30 Apr 2006 05:44:23 -0000      1.25
+@@ -35,11 +35,12 @@ static nis_result *result;
+ static nis_name tablename_val;
+ static u_long tablename_len;
+-#define NISENTRYVAL(idx,col,res) \
+-  ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
++#define NISENTRYVAL(idx, col, res) \
++  (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
++
++#define NISENTRYLEN(idx, col, res) \
++    (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
+-#define NISENTRYLEN(idx,col,res) \
+-    ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
+ static int
+ _nss_nisplus_parse_servent (nis_result *result, struct servent *serv,
+@@ -52,10 +53,9 @@ _nss_nisplus_parse_servent (nis_result *
+     return 0;
+   if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+-      || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
+-      || strcmp (result->objects.objects_val->EN_data.en_type,
+-               "services_tbl") != 0
+-      || result->objects.objects_val->EN_data.en_cols.en_cols_len < 4)
++      || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
++      || strcmp (NIS_RES_OBJECT (result)->EN_data.en_type, "services_tbl") != 0
++      || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 4)
+     return 0;
+   if (NISENTRYLEN (0, 0, result) >= room_left)
+@@ -68,8 +68,9 @@ _nss_nisplus_parse_servent (nis_result *
+            NISENTRYLEN (0, 0, result));
+   first_unused[NISENTRYLEN (0, 0, result)] = '\0';
+   serv->s_name = first_unused;
+-  room_left -= (strlen (first_unused) +1);
+-  first_unused += strlen (first_unused) +1;
++  size_t len = strlen (first_unused) + 1;
++  room_left -= len;
++  first_unused += len;
+   if (NISENTRYLEN (0, 2, result) >= room_left)
+     goto no_more_room;
+@@ -77,38 +78,43 @@ _nss_nisplus_parse_servent (nis_result *
+            NISENTRYLEN (0, 2, result));
+   first_unused[NISENTRYLEN (0, 2, result)] = '\0';
+   serv->s_proto = first_unused;
+-  room_left -= strlen (first_unused) + 1;
+-  first_unused += strlen (first_unused) + 1;
++  len = strlen (first_unused) + 1;
++  room_left -= len;
++  first_unused += len;
+   serv->s_port = htons (atoi (NISENTRYVAL (0, 3, result)));
+-  char *p = first_unused;
+-  char *line = p;
+-  for (unsigned int i = 0; i < result->objects.objects_len; ++i)
++  /* XXX Rewrite at some point to allocate the array first and then
++     copy the strings.  It wasteful to first concatenate the strings
++     to just split them again later.  */
++  char *line = first_unused;
++  for (unsigned int i = 0; i < NIS_RES_NUMOBJ (result); ++i)
+     {
+       if (strcmp (NISENTRYVAL (i, 1, result), serv->s_name) != 0)
+         {
+           if (NISENTRYLEN (i, 1, result) + 2 > room_left)
+             goto no_more_room;
+-        *p++ = ' ';
+-          p = __stpncpy (p, NISENTRYVAL (i, 1, result),
+-                       NISENTRYLEN (i, 1, result));
+-          *p = '\0';
+-          room_left -= (NISENTRYLEN (i, 1, result) + 1);
++        *first_unused++ = ' ';
++          first_unused = __stpncpy (first_unused, NISENTRYVAL (i, 1, result),
++                                  NISENTRYLEN (i, 1, result));
++          room_left -= NISENTRYLEN (i, 1, result) + 1;
+         }
+     }
+-  *p++ = '\0';
+-  first_unused = p;
++  *first_unused++ = '\0';
+   /* Adjust the pointer so it is aligned for
+      storing pointers.  */
+-  first_unused += __alignof__ (char *) - 1;
+-  first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *));
+-  serv->s_aliases = (char **) first_unused;
+-  if (room_left < sizeof (char *))
++  size_t adjust = ((__alignof__ (char *)
++                  - (first_unused - (char *) 0) % __alignof__ (char *))
++                 % __alignof__ (char *));
++  if (room_left < adjust + sizeof (char *))
+     goto no_more_room;
++  first_unused += adjust;
++  room_left -= adjust;
++  serv->s_aliases = (char **) first_unused;
++
++  /* For the terminating NULL pointer.  */
+   room_left -= (sizeof (char *));
+-  serv->s_aliases[0] = NULL;
+   unsigned int i = 0;
+   while (*line != '\0')
+@@ -124,24 +130,20 @@ _nss_nisplus_parse_servent (nis_result *
+         goto no_more_room;
+       room_left -= sizeof (char *);
+-      serv->s_aliases[i] = line;
++      serv->s_aliases[i++] = line;
+       while (*line != '\0' && *line != ' ')
+         ++line;
+       if (*line == ' ')
+-        {
+-        *line = '\0';
+-        ++line;
+-          ++i;
+-      }
+-      else
+-        serv->s_aliases[i+1] = NULL;
++      *line++ = '\0';
+     }
++  serv->s_aliases[i] = NULL;
+   return 1;
+ }
++
+ static enum nss_status
+ _nss_create_tablename (int *errnop)
+ {
+@@ -232,6 +234,11 @@ internal_nisplus_getservent_r (struct se
+           }
+         result = nis_first_entry (tablename_val);
++        if (result == NULL)
++          {
++            *errnop = errno;
++            return NSS_STATUS_TRYAGAIN;
++          }
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           return niserr2nss (result->status);
+       }
+@@ -239,6 +246,11 @@ internal_nisplus_getservent_r (struct se
+       {
+         saved_res = result;
+         result = nis_next_entry (tablename_val, &result->cookie);
++        if (result == NULL)
++          {
++            *errnop = errno;
++            return NSS_STATUS_TRYAGAIN;
++          }
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           {
+             nis_freeresult (saved_res);
+@@ -320,10 +332,10 @@ _nss_nisplus_getservbyname_r (const char
+        database is correct, we should find it in the first case, too */
+       if ((result->status != NIS_SUCCESS
+          && result->status != NIS_S_SUCCESS)
+-        || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
+-        || strcmp (result->objects.objects_val->EN_data.en_type,
++        || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
++        || strcmp (NIS_RES_OBJECT (result)->EN_data.en_type,
+                    "services_tbl") != 0
+-        || result->objects.objects_val->EN_data.en_cols.en_cols_len < 4)
++        || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 4)
+       snprintf (buf, sizeof (buf), "[cname=%s,proto=%s],%s", name, protocol,
+                 tablename_val);
+       else
+--- libc/nis/nss_nisplus/nisplus-spwd.c        3 Dec 2005 20:38:57 -0000       1.19
++++ libc/nis/nss_nisplus/nisplus-spwd.c        30 Apr 2006 05:44:23 -0000      1.20
+@@ -99,6 +99,11 @@ internal_nisplus_getspent_r (struct spwd
+           }
+         result = nis_first_entry (pwd_tablename_val);
++        if (result == NULL)
++          {
++            *errnop = errno;
++            return NSS_STATUS_TRYAGAIN;
++          }
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           return niserr2nss (result->status);
+       }
+@@ -106,6 +111,11 @@ internal_nisplus_getspent_r (struct spwd
+       {
+         saved_res = result;
+         result = nis_next_entry (pwd_tablename_val, &result->cookie);
++        if (result == NULL)
++          {
++            *errnop = errno;
++            return NSS_STATUS_TRYAGAIN;
++          }
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           {
+             nis_freeresult (saved_res);
+--- libc/nis/libnsl.h  1 Jan 1970 00:00:00 -0000
++++ libc/nis/libnsl.h  28 Apr 2006 21:01:49 -0000      1.2
+@@ -0,0 +1,25 @@
++/* Copyright (C) 2005, 2006 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.  */
++
++#define NSS_FLAG_NETID_AUTHORITATIVE  1
++#define NSS_FLAG_SERVICES_AUTHORITATIVE       2
++#define NSS_FLAG_SETENT_BATCH_READ    4
++
++
++/* Get current set of default flags.  */
++extern int _nsl_default_nss (void);
+--- libc/nis/nss-default.c     2006-04-19 19:21:31.748476000 +0200
++++ libc/nis/nss-default.c     2006-05-03 21:38:01.000000000 +0200
+@@ -0,0 +1,124 @@
++/* Copyright (C) 1996, 2001, 2004, 2006 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 <ctype.h>
++#include <stdio.h>
++#include <stdio_ext.h>
++#include <stdlib.h>
++#include <string.h>
++#include <bits/libc-lock.h>
++
++#include <libnsl.h>
++
++
++/* Path of the file.  */
++static const char default_nss[] = "/etc/default/nss";
++
++/* Flags once read from the file.  */
++static int default_nss_flags;
++
++/* Code to make sure we call 'init' once.  */
++__libc_once_define (static, once);
++
++/* Table of the recognized variables.  */
++static const struct
++{
++  char name[23];
++  unsigned int len;
++  int flag;
++} vars[] =
++  {
++#define STRNLEN(s) s, sizeof (s) - 1
++    { STRNLEN ("NETID_AUTHORITATIVE"), NSS_FLAG_NETID_AUTHORITATIVE },
++    { STRNLEN ("SERVICES_AUTHORITATIVE"), NSS_FLAG_SERVICES_AUTHORITATIVE },
++    { STRNLEN ("SETENT_BATCH_READ"), NSS_FLAG_SETENT_BATCH_READ }
++  };
++#define nvars (sizeof (vars) / sizeof (vars[0]))
++
++
++static void
++init (void)
++{
++  FILE *fp = fopen (default_nss, "rc");
++  if (fp != NULL)
++    {
++      char *line = NULL;
++      size_t linelen = 0;
++
++      __fsetlocking (fp, FSETLOCKING_BYCALLER);
++
++      while (!feof_unlocked (fp))
++      {
++        ssize_t n = getline (&line, &linelen, fp);
++        if (n <= 0)
++          break;
++
++        /* Recognize only
++
++             <THE-VARIABLE> = TRUE
++
++           with arbitrary white spaces.  */
++        char *cp = line;
++        while (isspace (*cp))
++          ++cp;
++
++        /* Recognize comment lines.  */
++        if (*cp == '#')
++          continue;
++
++        int idx;
++        for (idx = 0; idx < nvars; ++idx)
++          if (strncmp (cp, vars[idx].name, vars[idx].len) == 0)
++            break;
++        if (idx == nvars)
++          continue;
++
++        cp += vars[idx].len;
++        while (isspace (*cp))
++          ++cp;
++        if (*cp++ != '=')
++          continue;
++        while (isspace (*cp))
++          ++cp;
++
++        if (strncmp (cp, "TRUE", 4) != 0)
++          continue;
++        cp += 4;
++
++        while (isspace (*cp))
++          ++cp;
++
++        if (*cp == '\0')
++          default_nss_flags |= vars[idx].flag;
++      }
++
++      free (line);
++
++      fclose (fp);
++    }
++}
++
++
++int
++_nsl_default_nss (void)
++{
++  /* If we have not yet read the file yet do it now.  */
++  __libc_once (once, init);
++
++  return default_nss_flags;
++}
diff --git a/src/patches/glibc/glibc-nis+-batch2.patch b/src/patches/glibc/glibc-nis+-batch2.patch
new file mode 100644 (file)
index 0000000..93f5da6
--- /dev/null
@@ -0,0 +1,52 @@
+2006-05-18  Jakub Jelinek  <jakub@redhat.com>
+
+       * nis/nss_compat/compat-pwd.c (internal_setpwent): If nss_set*ent
+       returned NSS_STATUS_UNAVAIL, still return NSS_STATUS_SUCCESS.
+       * nis/nss_compat/compat-spwd.c (internal_setspent): Likewise.
+       * nis/nss_compat/compat-grp.c (internal_setgrent): Likewise.
+
+--- libc/nis/nss_compat/compat-grp.c   6 Jul 2005 21:04:53 -0000       1.30
++++ libc/nis/nss_compat/compat-grp.c   18 May 2006 14:51:05 -0000      1.31
+@@ -138,7 +138,11 @@ internal_setgrent (ent_t *ent, int stayo
+     rewind (ent->stream);
+   if (status == NSS_STATUS_SUCCESS && nss_setgrent)
+-    return nss_setgrent (stayopen);
++    {
++      status = nss_setgrent (stayopen);
++      if (status == NSS_STATUS_UNAVAIL)
++        status = NSS_STATUS_SUCCESS;
++    }
+   return status;
+ }
+--- libc/nis/nss_compat/compat-pwd.c   6 Jul 2005 21:03:32 -0000       1.35
++++ libc/nis/nss_compat/compat-pwd.c   18 May 2006 14:51:05 -0000      1.36
+@@ -258,7 +258,11 @@ internal_setpwent (ent_t *ent, int stayo
+   give_pwd_free (&ent->pwd);
+   if (status == NSS_STATUS_SUCCESS && nss_setpwent)
+-    return nss_setpwent (stayopen);
++    {
++      status = nss_setpwent (stayopen);
++      if (status == NSS_STATUS_UNAVAIL)
++        status = NSS_STATUS_SUCCESS;
++    }
+   return status;
+ }
+--- libc/nis/nss_compat/compat-spwd.c  6 Jul 2005 21:02:30 -0000       1.28
++++ libc/nis/nss_compat/compat-spwd.c  18 May 2006 14:51:05 -0000      1.29
+@@ -212,7 +212,11 @@ internal_setspent (ent_t *ent, int stayo
+   give_spwd_free (&ent->pwd);
+   if (status == NSS_STATUS_SUCCESS && nss_setspent)
+-    return nss_setspent (stayopen);
++    {
++      status = nss_setspent (stayopen);
++      if (status == NSS_STATUS_UNAVAIL)
++        status = NSS_STATUS_SUCCESS;
++    }
+   return status;
+ }
diff --git a/src/patches/glibc/glibc-nis+-findserver.patch b/src/patches/glibc/glibc-nis+-findserver.patch
new file mode 100644 (file)
index 0000000..9cb6565
--- /dev/null
@@ -0,0 +1,193 @@
+2006-08-07  Jakub Jelinek  <jakub@redhat.com>
+            Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_call.c (rec_dirsearch) [case LOWER_NAME]: Don't take
+       short cut if only one name component is stripped away.
+
+2006-08-07  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_call.c: Minor cleanups throughout.
+       (rec_dirsearch) [HIGHER_NAME]: Correctly size ndomain array.
+       (first_shoot): Add search_parent_first parameter.  Only if it is set
+       search parent server first.
+       If directory for table found through cold start cache is not the same
+       as referenced in the cache, don't use it.
+       (__nisfind_server): Take additional parameter.  Pass it on to
+       first_shoot.
+       (__prepare_niscall): Adjust __nisfind_server call.
+       * nis/rpcsvc/nislib.h: Adjust __nisfind_server prototype.
+       * nis/nis_table.c: Adjust __nisfind_server call.
+       * nis/nis_lookup.c: Likewise.
+       (nis_lookup): Don't loop endlessly if name is reduced to ".".
+
+--- libc/nis/nis_call.c        24 May 2006 07:30:09 -0000      1.29.4.6
++++ libc/nis/nis_call.c        7 Aug 2006 19:24:42 -0000
+@@ -125,7 +125,7 @@ __nisbind_connect (dir_binding *dbp)
+   dbp->addr.sin_addr.s_addr =
+     inetstr2int (serv->ep.ep_val[dbp->current_ep].uaddr);
+-  if (dbp->addr.sin_addr.s_addr == 0)
++  if (dbp->addr.sin_addr.s_addr == INADDR_NONE)
+     return NIS_FAIL;
+   /* Check, if the host is online and rpc.nisd is running. Much faster
+@@ -340,7 +340,7 @@ rec_dirsearch (const_nis_name name, dire
+     case HIGHER_NAME:
+       { /* We need data from a parent domain */
+       directory_obj *obj;
+-      char ndomain [strlen (name) + 3];
++      char ndomain[strlen (dir->do_name) + 3];
+       nis_domain_of_r (dir->do_name, ndomain, sizeof (ndomain));
+@@ -388,7 +388,6 @@ rec_dirsearch (const_nis_name name, dire
+       char domain[namelen + 3];
+       char ndomain[namelen + 3];
+       char *cp;
+-      u_int run = 0;
+       strcpy (domain, name);
+@@ -402,16 +401,9 @@ rec_dirsearch (const_nis_name name, dire
+           nis_leaf_of_r (domain, leaf, sizeof (leaf));
+           nis_domain_of_r (domain, ndomain, sizeof (ndomain));
+           strcpy (domain, ndomain);
+-          ++run;
+         }
+       while (nis_dir_cmp (domain, dir->do_name) != SAME_NAME);
+-      if (run == 1)
+-        {
+-          /* We have found the directory above. Use it. */
+-          return dir;
+-        }
+-
+       cp = strchr (leaf, '\0');
+       *cp++ = '.';
+       strcpy (cp, domain);
+@@ -461,31 +453,44 @@ rec_dirsearch (const_nis_name name, dire
+ /* We try to query the current server for the searched object,
+    maybe he know about it ? */
+ static directory_obj *
+-first_shoot (const_nis_name name, directory_obj *dir)
++first_shoot (const_nis_name name, int search_parent_first, directory_obj *dir)
+ {
+   directory_obj *obj = NULL;
+   fd_result *fd_res;
+   XDR xdrs;
+   char domain[strlen (name) + 3];
++#if 0
+   if (nis_dir_cmp (name, dir->do_name) == SAME_NAME)
+     return dir;
++#endif
+-  nis_domain_of_r (name, domain, sizeof (domain));
++  const char *search_name = name;
++  if (search_parent_first)
++    {
++      nis_domain_of_r (name, domain, sizeof (domain));
++      search_name = domain;
++    }
+-  if (nis_dir_cmp (domain, dir->do_name) == SAME_NAME)
++  if (nis_dir_cmp (search_name, dir->do_name) == SAME_NAME)
+     return dir;
+-  fd_res = __nis_finddirectory (dir, domain);
++  fd_res = __nis_finddirectory (dir, search_name);
+   if (fd_res == NULL)
+     return NULL;
+   if (fd_res->status == NIS_SUCCESS
+       && (obj = calloc (1, sizeof (directory_obj))) != NULL)
+     {
+-      xdrmem_create(&xdrs, fd_res->dir_data.dir_data_val,
+-                  fd_res->dir_data.dir_data_len, XDR_DECODE);
++      xdrmem_create (&xdrs, fd_res->dir_data.dir_data_val,
++                   fd_res->dir_data.dir_data_len, XDR_DECODE);
+       _xdr_directory_obj (&xdrs, obj);
+       xdr_destroy (&xdrs);
++
++      if (strcmp (dir->do_name, obj->do_name) != 0)
++      {
++        nis_free_directory (obj);
++        obj = NULL;
++      }
+     }
+   __free_fdresult (fd_res);
+@@ -497,7 +502,8 @@ first_shoot (const_nis_name name, direct
+ }
+ nis_error
+-__nisfind_server (const_nis_name name, directory_obj **dir)
++__nisfind_server (const_nis_name name, int search_parent_first,
++                directory_obj **dir)
+ {
+   if (name == NULL)
+     return NIS_BADNAME;
+@@ -520,7 +526,7 @@ __nisfind_server (const_nis_name name, d
+       return NIS_UNAVAIL;
+       /* Try at first, if servers in "dir" know our object */
+-      obj = first_shoot (name, *dir);
++      obj = first_shoot (name, search_parent_first, *dir);
+       if (obj == NULL)
+       {
+         obj = rec_dirsearch (name, *dir, &status);
+@@ -539,7 +545,7 @@ nis_error
+ __prepare_niscall (const_nis_name name, directory_obj **dirp,
+                  dir_binding *bptrp, unsigned int flags)
+ {
+-  nis_error retcode = __nisfind_server (name, dirp);
++  nis_error retcode = __nisfind_server (name, 1, dirp);
+   if (__builtin_expect (retcode != NIS_SUCCESS, 0))
+     return retcode;
+--- libc/nis/nis_lookup.c      24 May 2006 07:30:09 -0000      1.13.4.4
++++ libc/nis/nis_lookup.c      7 Aug 2006 19:24:42 -0000
+@@ -127,7 +127,7 @@ nis_lookup (const_nis_name name, const u
+                       /* Otherwise __nisfind_server will not do anything.  */
+                       dir = NULL;
+-                      if (__nisfind_server (req.ns_name, &dir)
++                      if (__nisfind_server (req.ns_name, 1, &dir)
+                           != NIS_SUCCESS)
+                         goto out;
+@@ -147,6 +147,11 @@ nis_lookup (const_nis_name name, const u
+                         nis_domain_of_r (req.ns_name, ndomain,
+                                          sizeof (ndomain));
+                         req.ns_name = strdupa (ndomain);
++                        if (strcmp (ndomain, ".") == 0)
++                          {
++                            NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
++                            goto out;
++                          }
+                         __nisbind_destroy (&bptr);
+                         nis_free_directory (dir);
+--- libc/nis/nis_table.c       21 May 2006 22:00:48 -0000      1.22.2.7
++++ libc/nis/nis_table.c       7 Aug 2006 19:24:42 -0000
+@@ -271,7 +271,8 @@ nis_list (const_nis_name name, unsigned 
+       memset (res, '\0', sizeof (nis_result));
+-      status = __nisfind_server (ibreq->ibr_name, &dir);
++      status = __nisfind_server (ibreq->ibr_name,
++                               ibreq->ibr_srch.ibr_srch_val != NULL, &dir);
+       if (status != NIS_SUCCESS)
+       {
+           NIS_RES_STATUS (res) = status;
+--- libc/nis/rpcsvc/nislib.h   6 Jul 2001 04:55:37 -0000       1.14
++++ libc/nis/rpcsvc/nislib.h   7 Aug 2006 19:24:42 -0000
+@@ -276,7 +276,8 @@ extern nis_error __nisbind_create (dir_b
+ extern nis_error __nisbind_connect (dir_binding *) __THROW;
+ extern nis_error __nisbind_next (dir_binding *) __THROW;
+ extern void __nisbind_destroy (dir_binding *) __THROW;
+-extern nis_error __nisfind_server (const_nis_name, directory_obj **) __THROW;
++extern nis_error __nisfind_server (const_nis_name, int, directory_obj **)
++     __THROW;
+ #endif
diff --git a/src/patches/glibc/glibc-nis+-getenv.patch b/src/patches/glibc/glibc-nis+-getenv.patch
new file mode 100644 (file)
index 0000000..09b6999
--- /dev/null
@@ -0,0 +1,32 @@
+2006-12-05  Jakub Jelinek  <jakub@redhat.com>
+
+       * nis/nis_subr.c (nis_getnames): Revert last change.
+
+2006-10-11  Jakub Jelinek  <jakub@redhat.com>
+
+       * nis/nis_defaults.c (__nis_default_access): Don't call getenv twice.
+
+       * nis/nis_subr.c (nis_getnames): Use __secure_getenv instead of getenv.
+       * sysdeps/generic/unsecvars.h: Add NIS_PATH.
+
+--- libc/nis/nis_defaults.c    10 May 2006 02:54:46 -0000      1.8
++++ libc/nis/nis_defaults.c    11 Oct 2006 16:22:34 -0000      1.9
+@@ -447,7 +447,7 @@ __nis_default_access (char *param, unsig
+     {
+       cptr = getenv ("NIS_DEFAULTS");
+       if (cptr != NULL && strstr (cptr, "access=") != NULL)
+-      result = searchaccess (getenv ("NIS_DEFAULTS"), result);
++      result = searchaccess (cptr, result);
+     }
+   return result;
+--- libc/sysdeps/generic/unsecvars.h   6 Jan 2005 22:40:19 -0000       1.8
++++ libc/sysdeps/generic/unsecvars.h   11 Oct 2006 16:24:05 -0000      1.9
+@@ -18,6 +18,7 @@
+   "LOCALDOMAIN\0"                                                           \
+   "LOCPATH\0"                                                               \
+   "MALLOC_TRACE\0"                                                          \
++  "NIS_PATH\0"                                                                      \
+   "NLSPATH\0"                                                               \
+   "RESOLV_HOST_CONF\0"                                                              \
+   "RES_OPTIONS\0"                                                           \
diff --git a/src/patches/glibc/glibc-nis+-getnames.patch b/src/patches/glibc/glibc-nis+-getnames.patch
new file mode 100644 (file)
index 0000000..bc3cf6f
--- /dev/null
@@ -0,0 +1,338 @@
+2006-06-16  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_subr.c (nis_getnames): Fix the implementation to better
+       match what Solaris does.
+
+2006-05-25  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_removemember.c (nis_removemember): Avoid unnecessary
+       copying.  No need to allocate new array for group members.  Just
+       move the pointers and update the size.
+
+       * nis/nis_addmember.c (nis_addmember): Avoid unnecessary copying.
+       Avoid memory leak in case realloc fails.  Simplification for
+       better code generation.
+
+       * nis/nis_callback.c (__nis_create_callback): Always call xdr_free
+       for cleanup when cb!=NULL [Coverity CID 233].
+
+--- libc/nis/nis_addmember.c   25 Oct 2004 03:15:59 -0000      1.7
++++ libc/nis/nis_addmember.c   25 May 2006 17:15:32 -0000      1.8
+@@ -28,13 +28,12 @@ nis_addmember (const_nis_name member, co
+     {
+       size_t grouplen = strlen (group);
+       char buf[grouplen + 14 + NIS_MAXNAMELEN];
+-      char leafbuf[grouplen + 2];
+       char domainbuf[grouplen + 2];
+       nis_result *res, *res2;
+       nis_error status;
+       char *cp, *cp2;
+-      cp = stpcpy (buf, nis_leaf_of_r (group, leafbuf, sizeof (leafbuf) - 1));
++      cp = rawmemchr (nis_leaf_of_r (group, buf, sizeof (buf) - 1), '\0');
+       cp = stpcpy (cp, ".groups_dir");
+       cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1);
+       if (cp2 != NULL && cp2[0] != '\0')
+@@ -42,30 +41,35 @@ nis_addmember (const_nis_name member, co
+         *cp++ = '.';
+           stpcpy (cp, cp2);
+         }
+-      res = nis_lookup (buf, FOLLOW_LINKS|EXPAND_NAME);
++      res = nis_lookup (buf, FOLLOW_LINKS | EXPAND_NAME);
+       if (NIS_RES_STATUS (res) != NIS_SUCCESS)
+       {
+         status = NIS_RES_STATUS (res);
+         nis_freeresult (res);
+         return status;
+       }
+-      if ((NIS_RES_NUMOBJ (res)  != 1) ||
+-          (__type_of (NIS_RES_OBJECT (res)) != NIS_GROUP_OBJ))
++      if (NIS_RES_NUMOBJ (res) != 1
++        || __type_of (NIS_RES_OBJECT (res)) != NIS_GROUP_OBJ)
+       {
+         nis_freeresult (res);
+         return NIS_INVALIDOBJ;
+       }
+-      NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val
++      u_int gr_members_len
++      = NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len;
++
++      nis_name *new_gr_members_val
+       = realloc (NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val,
+-                 (NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len + 1)
+-                 * sizeof (char *));
+-      if (NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val == NULL)
++                 (gr_members_len + 1) * sizeof (nis_name));
++      if (new_gr_members_val == NULL)
+       goto nomem_out;
+-      NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val[NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_len] = strdup (member);
+-      if (NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val[NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_len] == NULL)
++
++      NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val
++      = new_gr_members_val;
++
++      new_gr_members_val[gr_members_len] = strdup (member);
++      if (new_gr_members_val[gr_members_len] == NULL)
+       {
+-        free (NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val);
+       nomem_out:
+         nis_freeresult (res);
+         return NIS_NOMEMORY;
+--- libc/nis/nis_callback.c    20 May 2006 00:30:32 -0000      1.21
++++ libc/nis/nis_callback.c    25 May 2006 15:51:26 -0000      1.22
+@@ -360,8 +360,7 @@ __nis_create_callback (int (*callback) (
+     {
+       if (cb->xprt)
+       svc_destroy (cb->xprt);
+-      if (cb->serv)
+-      xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
++      xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
+       free (cb);
+     }
+   if (!nomsg)
+--- libc/nis/nis_removemember.c        7 Apr 2006 00:34:55 -0000       1.12
++++ libc/nis/nis_removemember.c        25 May 2006 18:30:53 -0000      1.13
+@@ -28,15 +28,12 @@ nis_removemember (const_nis_name member,
+     {
+       size_t grouplen = strlen (group);
+       char buf[grouplen + 14 + NIS_MAXNAMELEN];
+-      char leafbuf[grouplen + 2];
+       char domainbuf[grouplen + 2];
+-      nis_name *newmem;
+       nis_result *res, *res2;
+       nis_error status;
+       char *cp, *cp2;
+-      unsigned long int i, j, k;
+-      cp = stpcpy (buf, nis_leaf_of_r (group, leafbuf, sizeof (leafbuf) - 1));
++      cp = rawmemchr (nis_leaf_of_r (group, buf, sizeof (buf) - 1), '\0');
+       cp = stpcpy (cp, ".groups_dir");
+       cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1);
+       if (cp2 != NULL && cp2[0] != '\0')
+@@ -44,68 +41,41 @@ nis_removemember (const_nis_name member,
+           cp = stpcpy (cp, ".");
+           stpcpy (cp, cp2);
+         }
+-      res = nis_lookup (buf, FOLLOW_LINKS|EXPAND_NAME);
+-      if (res == NULL || NIS_RES_STATUS (res) != NIS_SUCCESS)
++      res = nis_lookup (buf, FOLLOW_LINKS | EXPAND_NAME);
++      if (res == NULL)
++      return NIS_NOMEMORY;
++      if (NIS_RES_STATUS (res) != NIS_SUCCESS)
+         {
+-        if (res)
+-          {
+-            status = NIS_RES_STATUS (res);
+-            nis_freeresult (res);
+-          }
+-        else
+-          return NIS_NOMEMORY;
++        status = NIS_RES_STATUS (res);
++        nis_freeresult (res);
+           return status;
+         }
+-      if ((res->objects.objects_len != 1) ||
+-          (__type_of (NIS_RES_OBJECT (res)) != NIS_GROUP_OBJ))
++      if (NIS_RES_NUMOBJ (res) != 1
++        || __type_of (NIS_RES_OBJECT (res)) != NIS_GROUP_OBJ)
+       {
+         nis_freeresult (res);
+         return NIS_INVALIDOBJ;
+       }
+-      newmem =
+-      calloc (NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len,
+-              sizeof (char *));
+-      if (newmem == NULL)
+-      {
+-        nis_freeresult (res);
+-        return NIS_NOMEMORY;
+-      }
+-
+-      k = NIS_RES_OBJECT (res)[0].GR_data.gr_members.gr_members_len;
+-      j = 0;
+-      for (i = 0; i < NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len;
+-         ++i)
+-      {
+-        if (strcmp (NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_val[i],
+-                    member) != 0)
+-          {
+-            newmem[j] = NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_val[i];
+-            ++j;
+-          }
+-        else
+-          {
+-            free (NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_val[i]);
+-            --k;
+-          }
+-      }
+-      free (NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val);
+-      assert (k <= NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len);
+-      /* This realloc() call always decreases the size.  This cannot
+-       fail.  We still have the test but do not recover memory
+-       (i.e., we overwrite the input pointer).  */
+-      nis_name *newp = realloc (newmem, k * sizeof (char*));
+-      if (newp == NULL)
+-      {
+-        free (newmem);
+-        nis_freeresult (res);
+-        return NIS_NOMEMORY;
+-      }
+-      newmem = newp;
+-
+-      NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val = newmem;
+-      NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_len = k;
++      nis_name *gr_members_val
++      = NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_val;
++      u_int gr_members_len
++      = NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len;
++
++      u_int j = 0;
++      for (u_int i = 0; i < gr_members_len; ++i)
++      if (strcmp (gr_members_val[i], member) != 0)
++        gr_members_val[j++] = gr_members_val[i];
++      else
++        free (gr_members_val[i]);
++
++      /* There is no need to reallocate the gr_members_val array.  We
++       just adjust the size to match the number of strings still in
++       it.  Yes, xdr_array will use mem_free with a size parameter
++       but this is mapped to a simple free call which determines the
++       size of the block by itself.  */
++      NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_len = j;
+       cp = stpcpy (buf, NIS_RES_OBJECT (res)->zo_name);
+       *cp++ = '.';
+--- libc/nis/nis_subr.c        16 Aug 2005 15:59:46 -0000      1.14
++++ libc/nis/nis_subr.c        16 Jun 2006 22:30:02 -0000      1.15
+@@ -107,25 +107,23 @@ count_dots (const_nis_name str)
+ nis_name *
+ nis_getnames (const_nis_name name)
+ {
+-  nis_name *getnames = NULL;
+-  char local_domain[NIS_MAXNAMELEN + 1];
++  const char *local_domain = nis_local_directory ();
++  size_t local_domain_len = strlen (local_domain);
++  size_t name_len = strlen (name);
+   char *path;
+-  char *cp;
+-  int count;
+   int pos = 0;
+-  int have_point;
+   char *saveptr;
++  int have_point;
++  const char *cp;
++  const char *cp2;
+-  strncpy (local_domain, nis_local_directory (), NIS_MAXNAMELEN);
+-  local_domain[NIS_MAXNAMELEN] = '\0';
+-
+-  count = 1;
+-  getnames = malloc ((count + 1) * sizeof (char *));
++  int count = 2;
++  nis_name *getnames = malloc ((count + 1) * sizeof (char *));
+   if (__builtin_expect (getnames == NULL, 0))
+       return NULL;
+   /* Do we have a fully qualified NIS+ name ? If yes, give it back */
+-  if (name[strlen (name) - 1] == '.')
++  if (name[name_len - 1] == '.')
+     {
+       if ((getnames[0] = strdup (name)) == NULL)
+       {
+@@ -141,6 +139,44 @@ nis_getnames (const_nis_name name)
+       return getnames;
+     }
++  /* If the passed NAME is shared a suffix (the latter of course with
++     a final dot) with each other we pass back NAME with a final
++     dot.  */
++  if (local_domain_len > 2)
++    {
++      have_point = 0;
++      cp = &local_domain[local_domain_len - 2];
++      cp2 = &name[name_len - 1];
++
++      while (*cp == *cp2)
++      {
++        if (*cp == '.')
++          have_point = 1;
++        --cp;
++        --cp2;
++        if (cp < local_domain)
++          {
++            have_point = cp2 < name || *cp2 == '.';
++            break;
++          }
++        if (cp2 < name)
++          {
++            have_point = *cp == '.';
++            break;
++          }
++      }
++
++      if (have_point)
++      {
++        getnames[0] = malloc (name_len + 2);
++        if (getnames[0] == NULL)
++          goto free_null;
++
++        strcpy (stpcpy (getnames[0], name), ".");
++        ++pos;
++      }
++    }
++
+   /* Get the search path, where we have to search "name" */
+   path = getenv ("NIS_PATH");
+   if (path == NULL)
+@@ -148,17 +184,17 @@ nis_getnames (const_nis_name name)
+   else
+     path = strdupa (path);
+-  have_point = (strchr (name, '.') != NULL);
++  have_point = strchr (name, '.') != NULL;
+   cp = __strtok_r (path, ":", &saveptr);
+   while (cp)
+     {
+       if (strcmp (cp, "$") == 0)
+       {
+-        char *cptr = local_domain;
++        const char *cptr = local_domain;
+         char *tmp;
+-        while ((have_point && *cptr != '\0') || (count_dots (cptr) >= 2))
++        while (*cptr != '\0' && count_dots (cptr) >= 2)
+           {
+             if (pos >= count)
+               {
+@@ -169,8 +205,7 @@ nis_getnames (const_nis_name name)
+                   goto free_null;
+                 getnames = newp;
+               }
+-            tmp = malloc (strlen (cptr) + strlen (local_domain) +
+-                          strlen (name) + 2);
++            tmp = malloc (strlen (cptr) + local_domain_len + name_len + 2);
+             if (__builtin_expect (tmp == NULL, 0))
+               goto free_null;
+@@ -200,7 +235,7 @@ nis_getnames (const_nis_name name)
+           {
+             char *p;
+-            tmp = malloc (cplen + strlen (local_domain) + strlen (name) + 2);
++            tmp = malloc (cplen + local_domain_len + name_len + 2);
+             if (__builtin_expect (tmp == NULL, 0))
+               goto free_null;
+@@ -216,7 +251,7 @@ nis_getnames (const_nis_name name)
+           {
+             char *p;
+-            tmp = malloc (cplen + strlen (name) + 2);
++            tmp = malloc (cplen + name_len + 2);
+             if (__builtin_expect (tmp == NULL, 0))
+               goto free_null;
diff --git a/src/patches/glibc/glibc-nis+-leaks.patch b/src/patches/glibc/glibc-nis+-leaks.patch
new file mode 100644 (file)
index 0000000..34e5534
--- /dev/null
@@ -0,0 +1,373 @@
+2006-05-04  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_table.c (get_tablepath): Renamed from __get_tablepath.
+       Adjust all callers.
+       Free res object content before returning.
+
+       * sunrpc/xdr_array.c (xdr_array): Use calloc instead of malloc&bzero.
+
+       * sunrpc/key_call.c (__rpc_thread_key_cleanup): Also free
+       client->cl_auth.
+
+       * sunrpc/rpc_thread.c (__rpc_thread_destroy): Don't skip entire
+       cleanup for initial thread, just the free call on TVP.
+
+--- libc/nis/nis_table.c       7 Apr 2006 00:56:07 -0000       1.32
++++ libc/nis/nis_table.c       5 May 2006 06:32:33 -0000       1.36
+@@ -25,7 +25,7 @@
+ static struct ib_request *
+-__create_ib_request (const_nis_name name, unsigned int flags)
++create_ib_request (const_nis_name name, unsigned int flags)
+ {
+   struct ib_request *ibreq = calloc (1, sizeof (struct ib_request));
+   nis_attr *search_val = NULL;
+@@ -91,13 +91,13 @@ __create_ib_request (const_nis_name name
+       if (cptr != NULL)
+       *cptr++ = '\0';
+-      if (!val)
++      if (__builtin_expect (val == NULL, 0))
+       {
+         nis_free_request (ibreq);
+         return NULL;
+       }
+       *val++ = '\0';
+-      if ((search_len + 1) >= size)
++      if (search_len + 1 >= size)
+         {
+           size += 1;
+         nis_attr *newp = realloc (search_val, size * sizeof (nis_attr));
+@@ -106,7 +106,7 @@ __create_ib_request (const_nis_name name
+         search_val = newp;
+       }
+       search_val[search_len].zattr_ndx = strdup (key);
+-      if ((search_val[search_len].zattr_ndx) == NULL)
++      if (search_val[search_len].zattr_ndx == NULL)
+       goto free_null;
+       search_val[search_len].zattr_val.zattr_val_len = strlen (val) + 1;
+@@ -129,7 +129,7 @@ __create_ib_request (const_nis_name name
+ static const struct timeval RPCTIMEOUT = {10, 0};
+ static char *
+-__get_tablepath (char *name, dir_binding *bptr)
++get_tablepath (char *name, dir_binding *bptr)
+ {
+   enum clnt_stat result;
+   nis_result res;
+@@ -152,7 +152,12 @@ __get_tablepath (char *name, dir_binding
+   else
+     cptr = "";
+-  return strdup (cptr);
++  char *str = strdup (cptr);
++
++  if (result == RPC_SUCCESS)
++    xdr_free ((xdrproc_t) _xdr_nis_result, (char *) &res);
++
++  return str;
+ }
+ nis_result *
+@@ -162,7 +167,7 @@ nis_list (const_nis_name name, unsigned 
+                          const void *userdata),
+         const void *userdata)
+ {
+-  nis_result *res = calloc (1, sizeof (nis_result));
++  nis_result *res = malloc (sizeof (nis_result));
+   ib_request *ibreq;
+   int status;
+   enum clnt_stat clnt_status;
+@@ -181,14 +186,18 @@ nis_list (const_nis_name name, unsigned 
+   if (name == NULL)
+     {
+-      NIS_RES_STATUS (res) = NIS_BADNAME;
++      status = NIS_BADNAME;
++    err_out:
++      memset (res, '\0', sizeof (nis_result));
++      NIS_RES_STATUS (res) = status;
+       return res;
+     }
+-  if ((ibreq = __create_ib_request (name, flags)) == NULL)
++  ibreq = create_ib_request (name, flags);
++  if (ibreq == NULL)
+     {
+-      NIS_RES_STATUS (res) = NIS_BADNAME;
+-      return res;
++      status = NIS_BADNAME;
++      goto err_out;
+     }
+   if ((flags & EXPAND_NAME)
+@@ -200,16 +209,16 @@ nis_list (const_nis_name name, unsigned 
+       if (names == NULL)
+       {
+         nis_free_request (ibreq);
+-        NIS_RES_STATUS (res) = NIS_BADNAME;
+-        return res;
++        status = NIS_BADNAME;
++        goto err_out;
+       }
+       ibreq->ibr_name = strdup (names[name_nr]);
+       if (ibreq->ibr_name == NULL)
+       {
+         nis_freenames (names);
+         nis_free_request (ibreq);
+-        NIS_RES_STATUS (res) = NIS_NOMEMORY;
+-        return res;
++        status = NIS_NOMEMORY;
++        goto err_out;
+       }
+     }
+   else
+@@ -236,14 +245,14 @@ nis_list (const_nis_name name, unsigned 
+       status = __nisbind_create (&bptr, dir->do_servers.do_servers_val,
+                                dir->do_servers.do_servers_len, flags);
+-      if (status != NIS_SUCCESS)
++      if (__builtin_expect (status != NIS_SUCCESS, 0))
+         {
+           NIS_RES_STATUS (res) = status;
+         goto fail2;
+         }
+       while (__nisbind_connect (&bptr) != NIS_SUCCESS)
+-      if (__nisbind_next (&bptr) != NIS_SUCCESS)
++      if (__builtin_expect (__nisbind_next (&bptr) != NIS_SUCCESS, 0))
+         {
+           NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
+           goto fail;
+@@ -262,7 +271,7 @@ nis_list (const_nis_name name, unsigned 
+                              (xdrproc_t) _xdr_nis_result,
+                              (caddr_t) res, RPCTIMEOUT);
+-      if (clnt_status != RPC_SUCCESS)
++      if (__builtin_expect (clnt_status != RPC_SUCCESS, 0))
+       NIS_RES_STATUS (res) = NIS_RPCERROR;
+       else
+       switch (NIS_RES_STATUS (res))
+@@ -276,7 +285,7 @@ nis_list (const_nis_name name, unsigned 
+               free (ibreq->ibr_name);
+               ibreq->ibr_name = NULL;
+               /* If we hit the link limit, bail.  */
+-              if (count_links > NIS_MAXLINKS)
++              if (__builtin_expect (count_links > NIS_MAXLINKS, 0))
+                 {
+                   NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
+                   ++done;
+@@ -335,7 +344,7 @@ nis_list (const_nis_name name, unsigned 
+             {
+               if (tablepath == NULL)
+                 {
+-                  tablepath = __get_tablepath (ibreq->ibr_name, &bptr);
++                  tablepath = get_tablepath (ibreq->ibr_name, &bptr);
+                   tableptr = tablepath;
+                 }
+               if (tableptr == NULL)
+@@ -400,7 +409,7 @@ nis_list (const_nis_name name, unsigned 
+                 {
+                   if (tablepath == NULL)
+                     {
+-                      tablepath = __get_tablepath (ibreq->ibr_name, &bptr);
++                      tablepath = get_tablepath (ibreq->ibr_name, &bptr);
+                       tableptr = tablepath;
+                     }
+                   if (tableptr == NULL)
+@@ -454,7 +463,7 @@ nis_list (const_nis_name name, unsigned 
+               /* Try the next domainname if we don't follow a link.  */
+               free (ibreq->ibr_name);
+               ibreq->ibr_name = NULL;
+-              if (count_links)
++              if (__builtin_expect (count_links, 0))
+                 {
+                   NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
+                   ++done;
+@@ -515,11 +524,7 @@ nis_add_entry (const_nis_name name, cons
+       return res;
+     }
+-  size_t namelen = strlen (name);
+-  char buf1[namelen + 20];
+-  char buf4[namelen + 20];
+-
+-  ib_request *ibreq = __create_ib_request (name, flags);
++  ib_request *ibreq = create_ib_request (name, flags);
+   if (ibreq == NULL)
+     {
+       NIS_RES_STATUS (res) = NIS_BADNAME;
+@@ -529,6 +534,10 @@ nis_add_entry (const_nis_name name, cons
+   nis_object obj;
+   memcpy (&obj, obj2, sizeof (nis_object));
++  size_t namelen = strlen (name);
++  char buf1[namelen + 20];
++  char buf4[namelen + 20];
++
+   if (obj.zo_name == NULL || strlen (obj.zo_name) == 0)
+     obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1));
+@@ -554,7 +563,7 @@ nis_add_entry (const_nis_name name, cons
+                                  (caddr_t) ibreq,
+                                  (xdrproc_t) _xdr_nis_result,
+                                  (caddr_t) res, 0, NULL);
+-  if (status  != NIS_SUCCESS)
++  if (__builtin_expect (status != NIS_SUCCESS, 0))
+     NIS_RES_STATUS (res) = status;
+   nis_free_request (ibreq);
+@@ -578,7 +587,8 @@ nis_modify_entry (const_nis_name name, c
+   if (res == NULL)
+     return NULL;
+-  if (( ibreq =__create_ib_request (name, flags)) == NULL)
++  ibreq = create_ib_request (name, flags);
++  if (ibreq == NULL)
+     {
+       NIS_RES_STATUS (res) = NIS_BADNAME;
+       return res;
+@@ -606,10 +616,11 @@ nis_modify_entry (const_nis_name name, c
+     }
+   ibreq->ibr_obj.ibr_obj_len = 1;
+-  if ((status = __do_niscall (ibreq->ibr_name, NIS_IBMODIFY,
+-                            (xdrproc_t) _xdr_ib_request,
+-                            (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
+-                            (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
++  status = __do_niscall (ibreq->ibr_name, NIS_IBMODIFY,
++                       (xdrproc_t) _xdr_ib_request,
++                       (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
++                       (caddr_t) res, 0, NULL);
++  if (__builtin_expect (status != NIS_SUCCESS, 0))
+     NIS_RES_STATUS (res) = status;
+   nis_free_request (ibreq);
+@@ -635,7 +646,8 @@ nis_remove_entry (const_nis_name name, c
+       return res;
+     }
+-  if ((ibreq =__create_ib_request (name, flags)) == NULL)
++  ibreq = create_ib_request (name, flags);
++  if (ibreq == NULL)
+     {
+       NIS_RES_STATUS (res) = NIS_BADNAME;
+       return res;
+@@ -681,7 +693,7 @@ nis_first_entry (const_nis_name name)
+       return res;
+     }
+-  ibreq = __create_ib_request (name, 0);
++  ibreq = create_ib_request (name, 0);
+   if (ibreq == NULL)
+     {
+       NIS_RES_STATUS (res) = NIS_BADNAME;
+@@ -693,7 +705,7 @@ nis_first_entry (const_nis_name name)
+                        (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
+                        (caddr_t) res, 0, NULL);
+-  if (status != NIS_SUCCESS)
++  if (__builtin_expect (status != NIS_SUCCESS, 0))
+     NIS_RES_STATUS (res) = status;
+   nis_free_request (ibreq);
+@@ -718,7 +730,7 @@ nis_next_entry (const_nis_name name, con
+       return res;
+     }
+-  ibreq = __create_ib_request (name, 0);
++  ibreq = create_ib_request (name, 0);
+   if (ibreq == NULL)
+     {
+       NIS_RES_STATUS (res) = NIS_BADNAME;
+@@ -736,7 +748,7 @@ nis_next_entry (const_nis_name name, con
+                        (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
+                        (caddr_t) res, 0, NULL);
+-  if (status != NIS_SUCCESS)
++  if (__builtin_expect (status != NIS_SUCCESS, 0))
+     NIS_RES_STATUS (res) = status;
+   if (cookie != NULL)
+--- libc/sunrpc/key_call.c     6 Mar 2005 00:25:54 -0000       1.19
++++ libc/sunrpc/key_call.c     4 May 2006 18:22:38 -0000       1.20
+@@ -552,8 +552,11 @@ __rpc_thread_key_cleanup (void)
+       struct key_call_private *kcp = RPC_THREAD_VARIABLE(key_call_private_s);
+       if (kcp) {
+-              if (kcp->client)
++              if (kcp->client) {
++                      if (kcp->client->cl_auth)
++                              auth_destroy (kcp->client->cl_auth);
+                       clnt_destroy(kcp->client);
++              }
+               free (kcp);
+       }
+ }
+--- libc/sunrpc/rpc_thread.c   22 Feb 2003 01:57:51 -0000      1.10
++++ libc/sunrpc/rpc_thread.c   4 May 2006 18:07:29 -0000       1.11
+@@ -20,7 +20,7 @@ __rpc_thread_destroy (void)
+ {
+       struct rpc_thread_variables *tvp = __libc_tsd_get (RPC_VARS);
+-      if (tvp != NULL && tvp != &__libc_tsd_RPC_VARS_mem) {
++      if (tvp != NULL) {
+               __rpc_thread_svc_cleanup ();
+               __rpc_thread_clnt_cleanup ();
+               __rpc_thread_key_cleanup ();
+@@ -29,7 +29,8 @@ __rpc_thread_destroy (void)
+               free (tvp->svcraw_private_s);
+               free (tvp->authdes_cache_s);
+               free (tvp->authdes_lru_s);
+-              free (tvp);
++              if (tvp != &__libc_tsd_RPC_VARS_mem)
++                      free (tvp);
+               __libc_tsd_set (RPC_VARS, NULL);
+       }
+ }
+--- libc/sunrpc/xdr_array.c    20 Jul 2005 17:50:28 -0000      1.9
++++ libc/sunrpc/xdr_array.c    4 May 2006 20:55:11 -0000       1.10
+@@ -74,7 +74,6 @@ xdr_array (xdrs, addrp, sizep, maxsize, 
+   caddr_t target = *addrp;
+   u_int c;            /* the actual element count */
+   bool_t stat = TRUE;
+-  u_int nodesize;
+   /* like strings, arrays are really counted arrays */
+   if (!INTUSE(xdr_u_int) (xdrs, sizep))
+@@ -90,7 +89,6 @@ xdr_array (xdrs, addrp, sizep, maxsize, 
+     {
+       return FALSE;
+     }
+-  nodesize = c * elsize;
+   /*
+    * if we are deserializing, we may need to allocate an array.
+@@ -102,7 +100,7 @@ xdr_array (xdrs, addrp, sizep, maxsize, 
+       case XDR_DECODE:
+       if (c == 0)
+         return TRUE;
+-      *addrp = target = mem_alloc (nodesize);
++      *addrp = target = calloc (c, elsize);
+       if (target == NULL)
+         {
+ #ifdef USE_IN_LIBIO
+@@ -114,7 +112,6 @@ xdr_array (xdrs, addrp, sizep, maxsize, 
+             (void) fputs (_("xdr_array: out of memory\n"), stderr);
+           return FALSE;
+         }
+-      __bzero (target, nodesize);
+       break;
+       case XDR_FREE:
+@@ -137,7 +134,7 @@ xdr_array (xdrs, addrp, sizep, maxsize, 
+    */
+   if (xdrs->x_op == XDR_FREE)
+     {
+-      mem_free (*addrp, nodesize);
++      mem_free (*addrp, c * elsize);
+       *addrp = NULL;
+     }
+   return stat;
diff --git a/src/patches/glibc/glibc-nis+-leaks2.patch b/src/patches/glibc/glibc-nis+-leaks2.patch
new file mode 100644 (file)
index 0000000..e9096f4
--- /dev/null
@@ -0,0 +1,15 @@
+2006-05-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * sunrpc/key_call.c (getkeyserv_handle): Call auth_destroy if
+       pid changed.
+
+--- libc/sunrpc/key_call.c     4 May 2006 18:22:38 -0000       1.20
++++ libc/sunrpc/key_call.c     17 May 2006 15:10:44 -0000      1.21
+@@ -400,6 +400,7 @@ getkeyserv_handle (int vers)
+   /* if pid has changed, destroy client and rebuild */
+   if (kcp->client != NULL && kcp->pid != __getpid ())
+     {
++      auth_destroy (kcp->client->cl_auth);
+       clnt_destroy (kcp->client);
+       kcp->client = NULL;
+     }
diff --git a/src/patches/glibc/glibc-nis+-parent.patch b/src/patches/glibc/glibc-nis+-parent.patch
new file mode 100644 (file)
index 0000000..93d5ed3
--- /dev/null
@@ -0,0 +1,1882 @@
+2006-05-23  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_lookup.c (nis_lookup): Use __prepare_niscall instead of
+       doing it all here.  When server does not know the answer do not
+       fail immediate, try parent first.
+
+       * nis/nis_domain_of_r.c (nis_domain_of_r): Add missing buffer
+       overflow test.
+
+2006-05-20  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_call.c (__prepare_niscall): New function.  Split out
+       from __do_niscall.
+       * nis/nis_table.c (__create_ib_request): Renamed from create_ib_request
+       and exported.
+       (__follow_path): New function.  Split out from nis_list.
+       * nis/nis_xdr.h: Add libnsl_hidden_proto for _xdr_ib_request and
+       _xdr_nis_result.
+       * nis/nis_xdr.c: Add libnsl_hidden_def for _xdr_ib_request and
+       _xdr_nis_result.
+       * nis/libnsl.h: Declare __prepare_niscall, __create_ib_request,
+       and __follow_path.
+       * nis/Versions: Export __prepare_niscall, __create_ib_request,
+       __follow_path, __do_niscall3, _xdr_ib_request, and _xdr_nis_result
+       from libnsl for version GLIBC_PRIVATE.
+       * nis/nisplus-parser.h: Remove _nss_nisplus_parse_pwent_chk.
+       Remove entry parameter from _nss_nisplus_parse_pwent and
+       _nss_nisplus_parse_grent.
+       * nis/nss_nisplus/nisplus-parser.c: Likewise.
+       * nis/nss_nisplus/nisplus-pwd.c: Remove support for SETENT_BATCH_READ
+       again.  Rewrite getpwent handling to not use nis_first_entry and
+       nis_next_entry.  Roll out own niscall handling.
+       * nis/nss_nisplus/nisplus-grp.c: Likewise.
+
+2006-05-19  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_call.c (__do_niscall3): Avoid code duplication in error
+       handling.
+
+       * nis/nis_callback.c (internal_nis_do_callback): Don't use malloc
+       to allocate memory for my_pollfd.  Better initialization of
+       cb_is_running.  Use TEMP_FAILURE_RETRY.
+
+       * nis/nis_callback.c (__nis_create_callback): Calls to
+       svcudp_bufcreate and svctcp_create can fail.  Free ->xprt if
+       asprintf call fails.
+
+2006-05-18  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_callback.c (__nis_create_callback): Use asprinf instead
+       of snprintf+strdup.  Handle OOM.
+       * nis/nis_callback.c (__nis_create_callback): Allocate cb and
+       cb->serv together.  Remove now obsolete free calls.
+       (__nis_destroy_callback): Remove now obsolete free call.
+
+2006-05-18  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_call.c (rec_dirsearch): Little optimization: pull
+       nis_free_directory forward to avoid duplication.
+
+2006-05-17  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_call.c (rec_dirsearch): Handle __nis_finddirectory and
+       rec_dirsearch returning NULL.
+       (first_shoot): Handle __nis_finddirectory returning NULL.
+       (__nisfind_server): Fix leak when rec_dirsearch returns NULL.
+
+--- libc/nis/Versions  14 Apr 2006 21:07:54 -0000      1.9
++++ libc/nis/Versions  20 May 2006 19:21:52 -0000      1.10
+@@ -58,7 +58,8 @@ libnsl {
+     xdr_ypall;
+   }
+   GLIBC_PRIVATE {
+-    _nsl_default_nss;
++    _nsl_default_nss; __prepare_niscall; __follow_path; __do_niscall3;
++    __create_ib_request; _xdr_ib_request; _xdr_nis_result;
+   }
+ }
+--- libc/nis/libnsl.h  28 Apr 2006 21:01:49 -0000      1.2
++++ libc/nis/libnsl.h  20 May 2006 20:17:22 -0000      1.4
+@@ -16,6 +16,8 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
++#include <rpcsvc/nis.h>
++
+ #define NSS_FLAG_NETID_AUTHORITATIVE  1
+ #define NSS_FLAG_SERVICES_AUTHORITATIVE       2
+ #define NSS_FLAG_SETENT_BATCH_READ    4
+@@ -23,3 +25,16 @@
+ /* Get current set of default flags.  */
+ extern int _nsl_default_nss (void);
++
++/* Set up everything for a call to __do_niscall3.  */
++extern nis_error __prepare_niscall (const_nis_name name, directory_obj **dirp,
++                                  dir_binding *bptrp, unsigned int flags);
++libnsl_hidden_proto (__prepare_niscall)
++
++extern struct ib_request *__create_ib_request (const_nis_name name,
++                                             unsigned int flags);
++libnsl_hidden_proto (__create_ib_request)
++
++extern nis_error __follow_path (char **tablepath, char **tableptr,
++                              struct ib_request *ibreq, dir_binding *bptr);
++libnsl_hidden_proto (__follow_path)
+--- libc/nis/nis_call.c        7 Apr 2006 06:53:11 -0000       1.37
++++ libc/nis/nis_call.c        24 May 2006 05:59:50 -0000      1.45
+@@ -30,6 +30,7 @@
+ #include "nis_xdr.h"
+ #include "nis_intern.h"
++#include <libnsl.h>
+ static const struct timeval RPCTIMEOUT = {10, 0};
+ static const struct timeval UDPTIMEOUT = {5, 0};
+@@ -256,6 +257,7 @@ __do_niscall3 (dir_binding *dbp, u_long 
+                 || ((nis_result *)resp)->status == NIS_NOSUCHNAME
+                 || ((nis_result *)resp)->status == NIS_NOT_ME)
+               {
++              next_server:
+                 if (__nisbind_next (dbp) == NIS_SUCCESS)
+                   {
+                     while (__nisbind_connect (dbp) != NIS_SUCCESS)
+@@ -273,38 +275,14 @@ __do_niscall3 (dir_binding *dbp, u_long 
+             if (((fd_result *)resp)->status == NIS_SYSTEMERROR
+                 || ((fd_result *)resp)->status == NIS_NOSUCHNAME
+                 || ((fd_result *)resp)->status == NIS_NOT_ME)
+-              {
+-                if (__nisbind_next (dbp) == NIS_SUCCESS)
+-                  {
+-                    while (__nisbind_connect (dbp) != NIS_SUCCESS)
+-                      {
+-                        if (__nisbind_next (dbp) != NIS_SUCCESS)
+-                          return NIS_SUCCESS;
+-                      }
+-                  }
+-                else
+-                  break; /* No more servers to search in */
+-                goto again;
+-              }
++              goto next_server;
+             break;
+           case NIS_DUMPLOG: /* log_result */
+           case NIS_DUMP:
+             if (((log_result *)resp)->lr_status == NIS_SYSTEMERROR
+                 || ((log_result *)resp)->lr_status == NIS_NOSUCHNAME
+                 || ((log_result *)resp)->lr_status == NIS_NOT_ME)
+-              {
+-                if (__nisbind_next (dbp) == NIS_SUCCESS)
+-                  {
+-                    while (__nisbind_connect (dbp) != NIS_SUCCESS)
+-                      {
+-                        if (__nisbind_next (dbp) != NIS_SUCCESS)
+-                          return NIS_SUCCESS;
+-                      }
+-                  }
+-                else
+-                  break; /* No more servers to search in */
+-                goto again;
+-              }
++              goto next_server;
+             break;
+           default:
+             break;
+@@ -316,6 +294,8 @@ __do_niscall3 (dir_binding *dbp, u_long 
+   return retcode;
+ }
++libnsl_hidden_def (__do_niscall3)
++
+ nis_error
+ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
+@@ -368,6 +348,12 @@ rec_dirsearch (const_nis_name name, dire
+          domain ! (Now I understand why a root server must be a
+          replica of the parent domain) */
+       fd_res = __nis_finddirectory (dir, ndomain);
++      if (fd_res == NULL)
++        {
++          nis_free_directory (dir);
++          *status = NIS_NOMEMORY;
++          return NULL;
++        }
+       *status = fd_res->status;
+       if (fd_res->status != NIS_SUCCESS)
+         {
+@@ -375,27 +361,25 @@ rec_dirsearch (const_nis_name name, dire
+           __free_fdresult (fd_res);
+           return dir;
+         }
++      nis_free_directory (dir);
+       obj = calloc (1, sizeof (directory_obj));
++      if (obj == NULL)
++        {
++          __free_fdresult (fd_res);
++          *status = NIS_NOMEMORY;
++          return NULL;
++        }
+       xdrmem_create (&xdrs, fd_res->dir_data.dir_data_val,
+                      fd_res->dir_data.dir_data_len, XDR_DECODE);
+       _xdr_directory_obj (&xdrs, obj);
+       xdr_destroy (&xdrs);
+       __free_fdresult (fd_res);
+-      if (obj != NULL)
+-        {
+-          /* We have found a NIS+ server serving ndomain, now
+-             let us search for "name" */
+-          nis_free_directory (dir);
+-          return rec_dirsearch (name, obj, status);
+-        }
+-      else
+-        {
+-          /* Ups, very bad. Are we already the root server ? */
+-          nis_free_directory (dir);
+-          return NULL;
+-        }
++
++      /* We have found a NIS+ server serving ndomain, now
++         let us search for "name" */
++      return rec_dirsearch (name, obj, status);
+       }
+-    break;
++      break;
+     case LOWER_NAME:
+       {
+       directory_obj *obj;
+@@ -433,6 +417,12 @@ rec_dirsearch (const_nis_name name, dire
+       strcpy (cp, domain);
+       fd_res = __nis_finddirectory (dir, leaf);
++      if (fd_res == NULL)
++        {
++          nis_free_directory (dir);
++          *status = NIS_NOMEMORY;
++          return NULL;
++        }
+       *status = fd_res->status;
+       if (fd_res->status != NIS_SUCCESS)
+         {
+@@ -440,21 +430,24 @@ rec_dirsearch (const_nis_name name, dire
+           __free_fdresult (fd_res);
+           return dir;
+         }
+-      obj = calloc(1, sizeof(directory_obj));
+-      xdrmem_create(&xdrs, fd_res->dir_data.dir_data_val,
+-                    fd_res->dir_data.dir_data_len, XDR_DECODE);
+-      _xdr_directory_obj(&xdrs, obj);
+-      xdr_destroy(&xdrs);
+-      __free_fdresult (fd_res);
+-      if (obj != NULL)
++      nis_free_directory (dir);
++      obj = calloc (1, sizeof(directory_obj));
++      if (obj == NULL)
+         {
+-          /* We have found a NIS+ server serving ndomain, now
+-             let us search for "name" */
+-          nis_free_directory (dir);
+-          return rec_dirsearch (name, obj, status);
++          __free_fdresult (fd_res);
++          *status = NIS_NOMEMORY;
++          return NULL;
+         }
++      xdrmem_create (&xdrs, fd_res->dir_data.dir_data_val,
++                     fd_res->dir_data.dir_data_len, XDR_DECODE);
++      _xdr_directory_obj (&xdrs, obj);
++      xdr_destroy (&xdrs);
++      __free_fdresult (fd_res);
++      /* We have found a NIS+ server serving ndomain, now
++         let us search for "name" */
++      return rec_dirsearch (name, obj, status);
+       }
+-    break;
++      break;
+     case BAD_NAME:
+       nis_free_directory (dir);
+       *status = NIS_BADNAME;
+@@ -484,6 +477,8 @@ first_shoot (const_nis_name name, direct
+     return dir;
+   fd_res = __nis_finddirectory (dir, domain);
++  if (fd_res == NULL)
++    return NULL;
+   if (fd_res->status == NIS_SUCCESS
+       && (obj = calloc (1, sizeof (directory_obj))) != NULL)
+     {
+@@ -513,74 +508,95 @@ __nisfind_server (const_nis_name name, d
+     dir = __nis_cache_search (name, flags, &cinfo);
+ #endif
++  nis_error result = NIS_SUCCESS;
+   if (*dir == NULL)
+     {
+       nis_error status;
+       directory_obj *obj;
+       *dir = readColdStartFile ();
+-      if (*dir == NULL) /* No /var/nis/NIS_COLD_START->no NIS+ installed */
++      if (*dir == NULL)
++      /* No /var/nis/NIS_COLD_START->no NIS+ installed.  */
+       return NIS_UNAVAIL;
+       /* Try at first, if servers in "dir" know our object */
+       obj = first_shoot (name, *dir);
+       if (obj == NULL)
+       {
+-        *dir = rec_dirsearch (name, *dir, &status);
+-        if (*dir == NULL)
+-          return status;
++        obj = rec_dirsearch (name, *dir, &status);
++        if (obj == NULL)
++          result = status;
+       }
+-      else
+-      *dir = obj;
++
++      *dir = obj;
+     }
+-  return NIS_SUCCESS;
++  return result;
+ }
++
+ nis_error
+-__do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs,
+-            caddr_t req, xdrproc_t xres, caddr_t resp, unsigned int flags,
+-            nis_cb *cb)
++__prepare_niscall (const_nis_name name, directory_obj **dirp,
++                 dir_binding *bptrp, unsigned int flags)
+ {
+-  nis_error retcode;
+-  dir_binding bptr;
+-  directory_obj *dir = NULL;
++  nis_error retcode = __nisfind_server (name, dirp);
++  if (__builtin_expect (retcode != NIS_SUCCESS, 0))
++    return retcode;
++
+   nis_server *server;
+   u_int server_len;
+-  int saved_errno = errno;
+-
+-  retcode = __nisfind_server (name, &dir);
+-  if (retcode != NIS_SUCCESS)
+-    return retcode;
+   if (flags & MASTER_ONLY)
+     {
+-      server = dir->do_servers.do_servers_val;
++      server = (*dirp)->do_servers.do_servers_val;
+       server_len = 1;
+     }
+   else
+     {
+-      server = dir->do_servers.do_servers_val;
+-      server_len = dir->do_servers.do_servers_len;
++      server = (*dirp)->do_servers.do_servers_val;
++      server_len = (*dirp)->do_servers.do_servers_len;
+     }
+-  retcode = __nisbind_create (&bptr, server, server_len, flags);
++  retcode = __nisbind_create (bptrp, server, server_len, flags);
++  if (retcode == NIS_SUCCESS)
++    {
++      do
++      if (__nisbind_connect (bptrp) == NIS_SUCCESS)
++        return NIS_SUCCESS;
++      while (__nisbind_next (bptrp) == NIS_SUCCESS);
++
++      __nisbind_destroy (bptrp);
++      memset (bptrp, '\0', sizeof (*bptrp));
++
++      retcode = NIS_NAMEUNREACHABLE;
++    }
++
++  nis_free_directory (*dirp);
++  *dirp = NULL;
++
++  return retcode;
++}
++libnsl_hidden_def (__prepare_niscall)
++
++
++nis_error
++__do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs,
++            caddr_t req, xdrproc_t xres, caddr_t resp, unsigned int flags,
++            nis_cb *cb)
++{
++  dir_binding bptr;
++  directory_obj *dir = NULL;
++  int saved_errno = errno;
++
++  nis_error retcode = __prepare_niscall (name, &dir, &bptr, flags);
+   if (retcode == NIS_SUCCESS)
+     {
+-      while (__nisbind_connect (&bptr) != NIS_SUCCESS)
+-      {
+-        if (__nisbind_next (&bptr) != NIS_SUCCESS)
+-          {
+-            nis_free_directory (dir);
+-            return NIS_NAMEUNREACHABLE;
+-          }
+-      }
+       retcode = __do_niscall3 (&bptr, prog, xargs, req, xres, resp, flags, cb);
+       __nisbind_destroy (&bptr);
+-    }
+-  nis_free_directory (dir);
++      nis_free_directory (dir);
++    }
+   __set_errno (saved_errno);
+--- libc/nis/nis_callback.c    17 Feb 2005 01:15:45 -0000      1.17
++++ libc/nis/nis_callback.c    20 May 2006 00:30:32 -0000      1.21
+@@ -197,22 +197,18 @@ internal_nis_do_callback (struct dir_bin
+                         struct nis_cb *cb)
+ {
+   struct timeval TIMEOUT = {25, 0};
+-  bool_t cb_is_running = FALSE;
++  bool_t cb_is_running;
+   data = cb;
+   for (;;)
+     {
+-      struct pollfd *my_pollfd;
++      struct pollfd my_pollfd[svc_max_pollfd];
+       int i;
+       if (svc_max_pollfd == 0 && svc_pollfd == NULL)
+         return NIS_CBERROR;
+-      my_pollfd = malloc (sizeof (struct pollfd) * svc_max_pollfd);
+-      if (__builtin_expect (my_pollfd == NULL, 0))
+-      return NIS_NOMEMORY;
+-
+       for (i = 0; i < svc_max_pollfd; ++i)
+         {
+           my_pollfd[i].fd = svc_pollfd[i].fd;
+@@ -220,20 +216,17 @@ internal_nis_do_callback (struct dir_bin
+           my_pollfd[i].revents = 0;
+         }
+-      switch (i = __poll (my_pollfd, svc_max_pollfd, 25*1000))
++      switch (i = TEMP_FAILURE_RETRY (__poll (my_pollfd, svc_max_pollfd,
++                                            25*1000)))
+         {
+       case -1:
+-        free (my_pollfd);
+-        if (errno == EINTR)
+-          continue;
+         return NIS_CBERROR;
+       case 0:
+-        free (my_pollfd);
+         /* See if callback 'thread' in the server is still alive. */
+-        memset ((char *) &cb_is_running, 0, sizeof (cb_is_running));
++        cb_is_running = FALSE;
+         if (clnt_call (bptr->clnt, NIS_CALLBACK, (xdrproc_t) xdr_netobj,
+                        (caddr_t) cookie, (xdrproc_t) xdr_bool,
+-                       (caddr_t) & cb_is_running, TIMEOUT) != RPC_SUCCESS)
++                       (caddr_t) &cb_is_running, TIMEOUT) != RPC_SUCCESS)
+           cb_is_running = FALSE;
+         if (cb_is_running == FALSE)
+@@ -244,7 +237,6 @@ internal_nis_do_callback (struct dir_bin
+         break;
+       default:
+         svc_getreq_poll (my_pollfd, i);
+-        free (my_pollfd);
+         if (data->nomore)
+           return data->result;
+       }
+@@ -275,15 +267,14 @@ __nis_create_callback (int (*callback) (
+   int sock = RPC_ANYSOCK;
+   struct sockaddr_in sin;
+   int len = sizeof (struct sockaddr_in);
+-  char addr[NIS_MAXNAMELEN + 1];
+   unsigned short port;
++  int nomsg = 0;
+-  cb = (struct nis_cb *) calloc (1, sizeof (struct nis_cb));
++  cb = (struct nis_cb *) calloc (1,
++                               sizeof (struct nis_cb) + sizeof (nis_server));
+   if (__builtin_expect (cb == NULL, 0))
+     goto failed;
+-  cb->serv = (nis_server *) calloc (1, sizeof (nis_server));
+-  if (__builtin_expect (cb->serv == NULL, 0))
+-    goto failed;
++  cb->serv = (nis_server *) (cb + 1);
+   cb->serv->name = strdup (nis_local_principal ());
+   if (__builtin_expect (cb->serv->name == NULL, 0))
+     goto failed;
+@@ -326,15 +317,20 @@ __nis_create_callback (int (*callback) (
+   cb->serv->ep.ep_val[0].proto = strdup ((flags & USE_DGRAM) ? "udp" : "tcp");
+   if (__builtin_expect (cb->serv->ep.ep_val[0].proto == NULL, 0))
+     goto failed;
+-  cb->xprt = (flags & USE_DGRAM) ? svcudp_bufcreate (sock, 100, 8192) :
+-                                 svctcp_create (sock, 100, 8192);
++  cb->xprt = ((flags & USE_DGRAM)
++            ? svcudp_bufcreate (sock, 100, 8192)
++            : svctcp_create (sock, 100, 8192));
++  if (cb->xprt == NULL)
++    {
++      nomsg = 1;
++      goto failed;
++    }
+   cb->sock = cb->xprt->xp_sock;
+   if (!svc_register (cb->xprt, CB_PROG, CB_VERS, cb_prog_1, 0))
+     {
+       xprt_unregister (cb->xprt);
+       svc_destroy (cb->xprt);
+       xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
+-      free (cb->serv);
+       free (cb);
+       syslog (LOG_ERR, "NIS+: failed to register callback dispatcher");
+       return NULL;
+@@ -345,30 +341,31 @@ __nis_create_callback (int (*callback) (
+       xprt_unregister (cb->xprt);
+       svc_destroy (cb->xprt);
+       xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
+-      free (cb->serv);
+       free (cb);
+       syslog (LOG_ERR, "NIS+: failed to read local socket info");
+       return NULL;
+     }
+   port = ntohs (sin.sin_port);
+   get_myaddress (&sin);
+-  snprintf (addr, sizeof (addr), "%s.%d.%d", inet_ntoa (sin.sin_addr),
+-          (port & 0xFF00) >> 8, port & 0x00FF);
+-  cb->serv->ep.ep_val[0].uaddr = strdup (addr);
++
++  if (asprintf (&cb->serv->ep.ep_val[0].uaddr, "%s.%d.%d",
++              inet_ntoa (sin.sin_addr), (port & 0xFF00) >> 8, port & 0x00FF)
++      < 0)
++    goto failed;
+   return cb;
+  failed:
+   if (cb)
+     {
++      if (cb->xprt)
++      svc_destroy (cb->xprt);
+       if (cb->serv)
+-      {
+-        xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
+-        free (cb->serv);
+-      }
++      xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
+       free (cb);
+     }
+-  syslog (LOG_ERR, "NIS+: out of memory allocating callback");
++  if (!nomsg)
++    syslog (LOG_ERR, "NIS+: out of memory allocating callback");
+   return NULL;
+ }
+@@ -379,7 +376,6 @@ __nis_destroy_callback (struct nis_cb *c
+   svc_destroy (cb->xprt);
+   close (cb->sock);
+   xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
+-  free (cb->serv);
+   free (cb);
+   return NIS_SUCCESS;
+--- libc/nis/nis_domain_of_r.c 15 Dec 2004 17:40:54 -0000      1.5
++++ libc/nis/nis_domain_of_r.c 24 May 2006 04:06:24 -0000      1.6
+@@ -29,6 +29,7 @@ nis_domain_of_r (const_nis_name name, ch
+   if (buffer == NULL)
+     {
++    erange:
+       __set_errno (ERANGE);
+       return NULL;
+     }
+@@ -44,7 +45,11 @@ nis_domain_of_r (const_nis_name name, ch
+   cptr_len = strlen (cptr);
+   if (cptr_len == 0)
+-    return strcpy (buffer, ".");
++    {
++      if (buflen < 2)
++      goto erange;
++      return strcpy (buffer, ".");
++    }
+   if (__builtin_expect (cptr_len >= buflen, 0))
+     {
+--- libc/nis/nis_intern.h      13 Dec 2001 03:38:06 -0000      1.20
++++ libc/nis/nis_intern.h      20 May 2006 20:18:03 -0000      1.21
+@@ -66,6 +66,7 @@ extern nis_error __do_niscall3 (dir_bind
+                               xdrproc_t xargs, caddr_t req,
+                               xdrproc_t xres, caddr_t resp,
+                               unsigned int flags, nis_cb *cb);
++libnsl_hidden_proto (__do_niscall3)
+ extern u_short __pmap_getnisport (struct sockaddr_in *address, u_long program,
+                                 u_long version, u_int protocol);
+--- libc/nis/nis_lookup.c      10 May 2006 02:30:20 -0000      1.18
++++ libc/nis/nis_lookup.c      24 May 2006 06:00:54 -0000      1.19
+@@ -21,6 +21,8 @@
+ #include <rpcsvc/nis.h>
+ #include "nis_xdr.h"
+ #include "nis_intern.h"
++#include <libnsl.h>
++
+ nis_result *
+ nis_lookup (const_nis_name name, const unsigned int flags)
+@@ -61,36 +63,18 @@ nis_lookup (const_nis_name name, const u
+       req.ns_object.ns_object_len = 0;
+       req.ns_object.ns_object_val = NULL;
+-      status = __nisfind_server (req.ns_name, &dir);
+-      if (status != NIS_SUCCESS)
++      status = __prepare_niscall (req.ns_name, &dir, &bptr, flags);
++      if (__builtin_expect (status != NIS_SUCCESS, 0))
+       {
+         NIS_RES_STATUS (res) = status;
+         goto out;
+       }
+-      status = __nisbind_create (&bptr, dir->do_servers.do_servers_val,
+-                               dir->do_servers.do_servers_len, flags);
+-      if (status != NIS_SUCCESS)
+-      {
+-        NIS_RES_STATUS (res) = status;
+-        nis_free_directory (dir);
+-        goto out;;
+-      }
+-
+-      while (__nisbind_connect (&bptr) != NIS_SUCCESS)
+-      {
+-        if (__nisbind_next (&bptr) != NIS_SUCCESS)
+-          {
+-            nis_free_directory (dir);
+-            NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
+-            goto out;
+-          }
+-      }
+-
+       do
+       {
+         static const struct timeval RPCTIMEOUT = {10, 0};
+         enum clnt_stat result;
++        char ndomain[strlen (req.ns_name) + 1];
+       again:
+         result = clnt_call (bptr.clnt, NIS_LOOKUP,
+@@ -106,11 +90,9 @@ nis_lookup (const_nis_name name, const u
+             if (NIS_RES_STATUS (res) == NIS_SUCCESS)
+               {
+-                  if (__type_of(NIS_RES_OBJECT (res)) == NIS_LINK_OBJ
++                  if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ
+                       && (flags & FOLLOW_LINKS)) /* We are following links */
+                     {
+-                      if (count_links)
+-                        free (req.ns_name);
+                       /* if we hit the link limit, bail */
+                       if (count_links > NIS_MAXLINKS)
+                         {
+@@ -119,31 +101,15 @@ nis_lookup (const_nis_name name, const u
+                         }
+                       ++count_links;
+                       req.ns_name =
+-                        strdup (NIS_RES_OBJECT (res)->LI_data.li_name);
+-                      if (req.ns_name == NULL)
+-                        {
+-                          nis_free_directory (dir);
+-                          res = NULL;
+-                          goto out;
+-                        }
++                        strdupa (NIS_RES_OBJECT (res)->LI_data.li_name);
+                       /* The following is a non-obvious optimization.  A
+                          nis_freeresult call would call xdr_free as the
+                          following code.  But it also would unnecessarily
+                          free the result structure.  We avoid this here
+                          along with the necessary tests.  */
+-#if 1
+                       xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res);
+                       memset (res, '\0', sizeof (*res));
+-#else
+-                      nis_freeresult (res);
+-                      res = calloc (1, sizeof (nis_result));
+-                      if (res == NULL)
+-                        {
+-                          __nisbind_destroy (&bptr);
+-                          return NULL;
+-                        }
+-#endif
+                       link_first_try = 1; /* Try at first the old binding */
+                       goto again;
+@@ -176,7 +142,24 @@ nis_lookup (const_nis_name name, const u
+                     }
+                   else
+                     if (__nisbind_next (&bptr) != NIS_SUCCESS)
+-                      break; /* No more servers to search */
++                      {
++                        /* No more servers to search.  Try parent.  */
++                        nis_domain_of_r (req.ns_name, ndomain,
++                                         sizeof (ndomain));
++                        req.ns_name = strdupa (ndomain);
++
++                        __nisbind_destroy (&bptr);
++                        nis_free_directory (dir);
++                        dir = NULL;
++                        status = __prepare_niscall (req.ns_name, &dir,
++                                                    &bptr, flags);
++                        if (__builtin_expect (status != NIS_SUCCESS, 0))
++                          {
++                            NIS_RES_STATUS (res) = status;
++                            goto out;
++                          }
++                        goto again;
++                      }
+                   while (__nisbind_connect (&bptr) != NIS_SUCCESS)
+                     {
+--- libc/nis/nis_table.c       5 May 2006 06:32:33 -0000       1.36
++++ libc/nis/nis_table.c       20 May 2006 19:14:20 -0000      1.37
+@@ -17,15 +17,17 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
++#include <assert.h>
+ #include <string.h>
+ #include <rpcsvc/nis.h>
+ #include "nis_xdr.h"
+ #include "nis_intern.h"
++#include "libnsl.h"
+-static struct ib_request *
+-create_ib_request (const_nis_name name, unsigned int flags)
++struct ib_request *
++__create_ib_request (const_nis_name name, unsigned int flags)
+ {
+   struct ib_request *ibreq = calloc (1, sizeof (struct ib_request));
+   nis_attr *search_val = NULL;
+@@ -125,6 +127,7 @@ create_ib_request (const_nis_name name, 
+   return ibreq;
+ }
++libnsl_hidden_def (__create_ib_request)
+ static const struct timeval RPCTIMEOUT = {10, 0};
+@@ -160,6 +163,38 @@ get_tablepath (char *name, dir_binding *
+   return str;
+ }
++
++nis_error
++__follow_path (char **tablepath, char **tableptr, struct ib_request *ibreq,
++             dir_binding *bptr)
++{
++  if (*tablepath == NULL)
++    {
++      *tablepath = get_tablepath (ibreq->ibr_name, bptr);
++      if (*tablepath == NULL)
++      return NIS_NOMEMORY;
++
++      *tableptr = *tablepath;
++    }
++  if (*tableptr == NULL)
++    return NIS_NOTFOUND;
++
++  char *newname = strsep (tableptr, ":");
++  if (newname[0] == '\0')
++    return NIS_NOTFOUND;
++
++  newname = strdup (newname);
++  if (newname == NULL)
++    return NIS_NOMEMORY;
++
++  free (ibreq->ibr_name);
++  ibreq->ibr_name = newname;
++
++  return NIS_SUCCESS;
++}
++libnsl_hidden_def (__follow_path)
++
++
+ nis_result *
+ nis_list (const_nis_name name, unsigned int flags,
+         int (*callback) (const_nis_name name,
+@@ -193,7 +228,7 @@ nis_list (const_nis_name name, unsigned 
+       return res;
+     }
+-  ibreq = create_ib_request (name, flags);
++  ibreq = __create_ib_request (name, flags);
+   if (ibreq == NULL)
+     {
+       status = NIS_BADNAME;
+@@ -260,6 +295,7 @@ nis_list (const_nis_name name, unsigned 
+       if (callback != NULL)
+       {
++        assert (cb == NULL);
+         cb = __nis_create_callback (callback, userdata, flags);
+         ibreq->ibr_cbhost.ibr_cbhost_len = 1;
+         ibreq->ibr_cbhost.ibr_cbhost_val = cb->serv;
+@@ -327,69 +363,30 @@ nis_list (const_nis_name name, unsigned 
+                  following code.  But it also would unnecessarily
+                  free the result structure.  We avoid this here
+                  along with the necessary tests.  */
+-#if 1
+               xdr_free ((xdrproc_t) _xdr_nis_result, (char *)res);
+               memset (res, '\0', sizeof (*res));
+-#else
+-              nis_freeresult (res);
+-              res = calloc (1, sizeof (nis_result));
+-              if (res == NULL)
+-                goto fail;
+-#endif
+               first_try = 1; /* Try at first the old binding */
+               goto again;
+             }
+           else if ((flags & FOLLOW_PATH)
+                    && NIS_RES_STATUS (res) == NIS_PARTIAL)
+             {
+-              if (tablepath == NULL)
+-                {
+-                  tablepath = get_tablepath (ibreq->ibr_name, &bptr);
+-                  tableptr = tablepath;
+-                }
+-              if (tableptr == NULL)
++              clnt_status = __follow_path (&tablepath, &tableptr, ibreq,
++                                           &bptr);
++              if (clnt_status != NIS_SUCCESS)
+                 {
+-                  ++done;
+-                  break;
+-                }
+-              free (ibreq->ibr_name);
+-              ibreq->ibr_name = strsep (&tableptr, ":");
+-              if (ibreq->ibr_name == NULL || ibreq->ibr_name[0] == '\0')
+-                {
+-                  ibreq->ibr_name = strdup ("");
+-                  if (ibreq->ibr_name == NULL)
+-                    {
+-                      NIS_RES_STATUS (res) = NIS_NOMEMORY;
+-                      goto fail;
+-                    }
++                  NIS_RES_STATUS (res) = clnt_status;
+                   ++done;
+                 }
+               else
+                 {
+-                  ibreq->ibr_name = strdup (ibreq->ibr_name);
+                   /* The following is a non-obvious optimization.  A
+                      nis_freeresult call would call xdr_free as the
+                      following code.  But it also would unnecessarily
+                      free the result structure.  We avoid this here
+                      along with the necessary tests.  */
+-#if 1
+-                  xdr_free ((xdrproc_t) _xdr_nis_result, (char *)res);
++                  xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res);
+                   memset (res, '\0', sizeof (*res));
+-                  if (ibreq->ibr_name == NULL)
+-                    {
+-                      NIS_RES_STATUS (res) = NIS_NOMEMORY;
+-                      goto fail;
+-                    }
+-#else
+-                  nis_freeresult (res);
+-                  res = calloc (1, sizeof (nis_result));
+-                  if (res == NULL || ibreq->ibr_name == NULL)
+-                    {
+-                      free (res);
+-                      res = NULL;
+-                      goto fail;
+-                    }
+-#endif
+                   first_try = 1;
+                   goto again;
+                 }
+@@ -407,30 +404,10 @@ nis_list (const_nis_name name, unsigned 
+                 ++done;
+               else
+                 {
+-                  if (tablepath == NULL)
+-                    {
+-                      tablepath = get_tablepath (ibreq->ibr_name, &bptr);
+-                      tableptr = tablepath;
+-                    }
+-                  if (tableptr == NULL)
+-                    {
+-                      ++done;
+-                      break;
+-                    }
+-                  free (ibreq->ibr_name);
+-                  ibreq->ibr_name = strsep (&tableptr, ":");
+-                  if (ibreq->ibr_name == NULL || ibreq->ibr_name[0] == '\0')
+-                    {
+-                      ibreq->ibr_name = strdup ("");
+-                      ++done;
+-                    }
+-                  else
+-                    ibreq->ibr_name = strdup (ibreq->ibr_name);
+-                  if (ibreq->ibr_name == NULL)
+-                    {
+-                      NIS_RES_STATUS (res) = NIS_NOMEMORY;
+-                      goto fail;
+-                    }
++                  NIS_RES_STATUS (res)
++                    = __follow_path (&tablepath, &tableptr, ibreq, &bptr);
++                  if (NIS_RES_STATUS (res) != NIS_SUCCESS)
++                    ++done;
+                 }
+             }
+           break;
+@@ -524,7 +501,7 @@ nis_add_entry (const_nis_name name, cons
+       return res;
+     }
+-  ib_request *ibreq = create_ib_request (name, flags);
++  ib_request *ibreq = __create_ib_request (name, flags);
+   if (ibreq == NULL)
+     {
+       NIS_RES_STATUS (res) = NIS_BADNAME;
+@@ -587,7 +564,7 @@ nis_modify_entry (const_nis_name name, c
+   if (res == NULL)
+     return NULL;
+-  ibreq = create_ib_request (name, flags);
++  ibreq = __create_ib_request (name, flags);
+   if (ibreq == NULL)
+     {
+       NIS_RES_STATUS (res) = NIS_BADNAME;
+@@ -646,7 +623,7 @@ nis_remove_entry (const_nis_name name, c
+       return res;
+     }
+-  ibreq = create_ib_request (name, flags);
++  ibreq = __create_ib_request (name, flags);
+   if (ibreq == NULL)
+     {
+       NIS_RES_STATUS (res) = NIS_BADNAME;
+@@ -693,7 +670,7 @@ nis_first_entry (const_nis_name name)
+       return res;
+     }
+-  ibreq = create_ib_request (name, 0);
++  ibreq = __create_ib_request (name, 0);
+   if (ibreq == NULL)
+     {
+       NIS_RES_STATUS (res) = NIS_BADNAME;
+@@ -730,7 +707,7 @@ nis_next_entry (const_nis_name name, con
+       return res;
+     }
+-  ibreq = create_ib_request (name, 0);
++  ibreq = __create_ib_request (name, 0);
+   if (ibreq == NULL)
+     {
+       NIS_RES_STATUS (res) = NIS_BADNAME;
+--- libc/nis/nis_xdr.c 12 May 2006 02:39:20 -0000      1.11
++++ libc/nis/nis_xdr.c 20 May 2006 19:15:24 -0000      1.12
+@@ -308,6 +308,7 @@ _xdr_nis_result (XDR *xdrs, nis_result *
+     }
+   return res;
+ }
++libnsl_hidden_def (_xdr_nis_result)
+ bool_t
+ _xdr_ns_request (XDR *xdrs, ns_request *objp)
+@@ -357,6 +358,7 @@ _xdr_ib_request (XDR *xdrs, ib_request *
+     }
+   return res;
+ }
++libnsl_hidden_def (_xdr_ib_request)
+ bool_t
+ _xdr_ping_args (XDR *xdrs, ping_args *objp)
+--- libc/nis/nis_xdr.h 11 May 2006 20:35:47 -0000      1.4
++++ libc/nis/nis_xdr.h 20 May 2006 19:16:04 -0000      1.5
+@@ -30,9 +30,7 @@ extern  bool_t _xdr_nis_server (XDR *, n
+ extern  bool_t _xdr_directory_obj (XDR *, directory_obj*);
+ extern  bool_t _xdr_nis_object (XDR *, nis_object*);
+ extern  bool_t _xdr_nis_error (XDR *, nis_error*);
+-extern  bool_t _xdr_nis_result (XDR *, nis_result*);
+ extern  bool_t _xdr_ns_request (XDR *, ns_request*);
+-extern  bool_t _xdr_ib_request (XDR *, ib_request*);
+ extern  bool_t _xdr_ping_args (XDR *, ping_args*);
+ extern  bool_t _xdr_cp_result (XDR *, cp_result*);
+ extern  bool_t _xdr_nis_tag (XDR *, nis_tag*);
+@@ -42,4 +40,9 @@ extern  bool_t _xdr_fd_result (XDR *, fd
+ __END_DECLS
++extern  bool_t _xdr_ib_request (XDR *, ib_request*);
++libnsl_hidden_proto (_xdr_ib_request)
++extern  bool_t _xdr_nis_result (XDR *, nis_result*);
++libnsl_hidden_proto (_xdr_nis_result)
++
+ #endif
+--- libc/nis/nisplus-parser.h  29 Apr 2006 20:16:35 -0000      1.6
++++ libc/nis/nisplus-parser.h  20 May 2006 19:17:04 -0000      1.7
+@@ -24,15 +24,12 @@
+ #include <grp.h>
+ #include <shadow.h>
+-extern int _nss_nisplus_parse_pwent (nis_result *result, size_t entry,
+-                                   struct passwd *pw, char *buffer,
+-                                   size_t buflen, int *errnop);
+-extern int _nss_nisplus_parse_pwent_chk (nis_result *result, struct passwd *pw,
+-                                       char *buffer, size_t buflen,
+-                                       int *errnop);
+-extern int _nss_nisplus_parse_grent (nis_result *result, u_long entry,
+-                                   struct group *gr, char *buffer,
+-                                   size_t buflen, int *errnop);
++extern int _nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw,
++                                   char *buffer, size_t buflen, int *errnop);
++
++extern int _nss_nisplus_parse_grent (nis_result *result, struct group *gr,
++                                   char *buffer, size_t buflen, int *errnop);
++
+ extern int _nss_nisplus_parse_spent (nis_result *result, struct spwd *sp,
+                                    char *buffer, size_t buflen, int *errnop);
+--- libc/nis/nss_nisplus/nisplus-grp.c 25 Mar 2006 20:59:19 -0000      1.19
++++ libc/nis/nss_nisplus/nisplus-grp.c 20 May 2006 19:20:19 -0000      1.20
+@@ -29,12 +29,23 @@
+ #include "nss-nisplus.h"
+ #include "nisplus-parser.h"
++#include <libnsl.h>
++#include <nis_intern.h>
++#include <nis_xdr.h>
+ __libc_lock_define_initialized (static, lock);
+-static nis_result *result;
+-static unsigned long next_entry;
++/* Connection information.  */
++static ib_request *ibreq;
++static directory_obj *dir;
++static dir_binding bptr;
++static char *tablepath;
++static char *tableptr;
++/* Cursor.  */
++static netobj cursor;
++
++
+ static nis_name tablename_val;
+ static size_t tablename_len;
+@@ -66,43 +77,57 @@ _nss_create_tablename (int *errnop)
+   return NSS_STATUS_SUCCESS;
+ }
+-static enum nss_status
+-internal_setgrent (void)
++
++static void
++internal_endgrent (void)
+ {
+-  enum nss_status status;
++  __nisbind_destroy (&bptr);
++  memset (&bptr, '\0', sizeof (bptr));
+-  if (result != NULL)
+-    {
+-      nis_freeresult (result);
+-      result = NULL;
+-    }
+-  next_entry = 0;
++  nis_free_directory (dir);
++  dir = NULL;
++
++  nis_free_request (ibreq);
++  ibreq = NULL;
++
++  xdr_free ((xdrproc_t) xdr_netobj, (char *) &cursor);
++  memset (&cursor, '\0', sizeof (cursor));
++
++  free (tablepath);
++  tableptr = tablepath = NULL;
++}
++
++
++static enum nss_status
++internal_setgrent (int *errnop)
++{
++  enum nss_status status = NSS_STATUS_SUCCESS;
+   if (tablename_val == NULL)
+-    {
+-      int err;
+-      if (_nss_create_tablename (&err) != NSS_STATUS_SUCCESS)
+-      return NSS_STATUS_UNAVAIL;
+-    }
++    status = _nss_create_tablename (errnop);
+-  result = nis_list (tablename_val, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
+-  if (result == NULL)
++  if (status == NSS_STATUS_SUCCESS)
+     {
+-      status = NSS_STATUS_TRYAGAIN;
+-      __set_errno (ENOMEM);
+-    }
+-  else
+-    {
+-      status = niserr2nss (result->status);
+-      if (status != NSS_STATUS_SUCCESS)
++      ibreq = __create_ib_request (tablename_val, 0);
++      if (ibreq == NULL)
+       {
+-        nis_freeresult (result);
+-        result = NULL;
++        *errnop = errno;
++        return NSS_STATUS_TRYAGAIN;
++      }
++
++      nis_error retcode = __prepare_niscall (tablename_val, &dir, &bptr, 0);
++      if (retcode != NIS_SUCCESS)
++      {
++        nis_free_request (ibreq);
++        ibreq = NULL;
++        status = niserr2nss (retcode);
+       }
+     }
++
+   return status;
+ }
++
+ enum nss_status
+ _nss_nisplus_setgrent (int stayopen)
+ {
+@@ -110,60 +135,133 @@ _nss_nisplus_setgrent (int stayopen)
+   __libc_lock_lock (lock);
+-  status = internal_setgrent ();
++  internal_endgrent ();
++
++  // XXX We need to be able to set errno.  Pass in new parameter.
++  int err;
++  status = internal_setgrent (&err);
+   __libc_lock_unlock (lock);
+   return status;
+ }
++
+ enum nss_status
+ _nss_nisplus_endgrent (void)
+ {
+   __libc_lock_lock (lock);
+-  if (result != NULL)
+-    {
+-      nis_freeresult (result);
+-      result = NULL;
+-    }
++  internal_endgrent ();
+   __libc_lock_unlock (lock);
+   return NSS_STATUS_SUCCESS;
+ }
++
+ static enum nss_status
+ internal_nisplus_getgrent_r (struct group *gr, char *buffer, size_t buflen,
+                            int *errnop)
+ {
+-  int parse_res;
+-
+-  if (result == NULL)
+-    {
+-      enum nss_status status;
+-
+-      status = internal_setgrent ();
+-      if (result == NULL || status != NSS_STATUS_SUCCESS)
+-      return status;
+-    }
++  int parse_res = -1;
++  enum nss_status retval = NSS_STATUS_SUCCESS;
+   /* Get the next entry until we found a correct one. */
+   do
+     {
+-      if (next_entry >= result->objects.objects_len)
+-      return NSS_STATUS_NOTFOUND;
++      nis_error status;
++      nis_result result;
++      memset (&result, '\0', sizeof (result));
++
++      if (cursor.n_bytes == NULL)
++      {
++        if (ibreq == NULL)
++          {
++            retval = internal_setgrent (errnop);
++            if (retval != NSS_STATUS_SUCCESS)
++              return retval;
++          }
++
++        status = __do_niscall3 (&bptr, NIS_IBFIRST,
++                                (xdrproc_t) _xdr_ib_request,
++                                (caddr_t) ibreq,
++                                (xdrproc_t) _xdr_nis_result,
++                                (caddr_t) &result,
++                                0, NULL);
++      }
++      else
++      {
++        ibreq->ibr_cookie.n_bytes = cursor.n_bytes;
++        ibreq->ibr_cookie.n_len = cursor.n_len;
++
++        status = __do_niscall3 (&bptr, NIS_IBNEXT,
++                                (xdrproc_t) _xdr_ib_request,
++                                (caddr_t) ibreq,
++                                (xdrproc_t) _xdr_nis_result,
++                                (caddr_t) &result,
++                                0, NULL);
+-      parse_res = _nss_nisplus_parse_grent (result, next_entry, gr,
++        ibreq->ibr_cookie.n_bytes = NULL;
++        ibreq->ibr_cookie.n_len = 0;
++      }
++
++      if (status != NIS_SUCCESS)
++      return niserr2nss (status);
++
++      if (NIS_RES_STATUS (&result) == NIS_NOTFOUND)
++      {
++        /* No more entries on this server.  This means we have to go
++           to the next server on the path.  */
++        status = __follow_path (&tablepath, &tableptr, ibreq, &bptr);
++        if (status != NIS_SUCCESS)
++          return niserr2nss (status);
++
++        directory_obj *newdir = NULL;
++        dir_binding newbptr;
++        status = __prepare_niscall (ibreq->ibr_name, &newdir, &newbptr, 0);
++        if (status != NIS_SUCCESS)
++          return niserr2nss (status);
++
++        nis_free_directory (dir);
++        dir = newdir;
++        __nisbind_destroy (&bptr);
++        bptr = newbptr;
++
++        xdr_free ((xdrproc_t) xdr_netobj, (char *) &result.cookie);
++        result.cookie.n_bytes = NULL;
++        result.cookie.n_len = 0;
++        parse_res = 0;
++        goto next;
++      }
++      else if (NIS_RES_STATUS (&result) != NIS_SUCCESS)
++      return niserr2nss (NIS_RES_STATUS (&result));
++
++      parse_res = _nss_nisplus_parse_grent (&result, gr,
+                                           buffer, buflen, errnop);
+-      if (parse_res == -1)
+-      return NSS_STATUS_TRYAGAIN;
++      if (__builtin_expect (parse_res == -1, 0))
++      {
++        *errnop = ERANGE;
++        retval = NSS_STATUS_TRYAGAIN;
++        goto freeres;
++      }
+-      ++next_entry;
++    next:
++      /* Free the old cursor.  */
++      xdr_free ((xdrproc_t) xdr_netobj, (char *) &cursor);
++      /* Remember the new one.  */
++      cursor.n_bytes = result.cookie.n_bytes;
++      cursor.n_len = result.cookie.n_len;
++      /* Free the result structure.  NB: we do not remove the cookie.  */
++      result.cookie.n_bytes = NULL;
++      result.cookie.n_len = 0;
++    freeres:
++      xdr_free ((xdrproc_t) _xdr_nis_result, (char *) &result);
++      memset (&result, '\0', sizeof (result));
+     }
+   while (!parse_res);
+-  return NSS_STATUS_SUCCESS;
++  return retval;
+ }
+ enum nss_status
+@@ -227,7 +325,7 @@ _nss_nisplus_getgrnam_r (const char *nam
+       return status;
+     }
+-  parse_res = _nss_nisplus_parse_grent (result, 0, gr, buffer, buflen, errnop);
++  parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen, errnop);
+   nis_freeresult (result);
+   if (__builtin_expect (parse_res < 1, 0))
+     {
+@@ -288,7 +386,7 @@ _nss_nisplus_getgrgid_r (const gid_t gid
+       return status;
+     }
+-  parse_res = _nss_nisplus_parse_grent (result, 0, gr, buffer, buflen, errnop);
++  parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen, errnop);
+   nis_freeresult (result);
+   if (__builtin_expect (parse_res < 1, 0))
+--- libc/nis/nss_nisplus/nisplus-parser.c      30 Apr 2006 07:00:12 -0000      1.16
++++ libc/nis/nss_nisplus/nisplus-parser.c      20 May 2006 19:17:59 -0000      1.17
+@@ -31,10 +31,16 @@
+ #define NISENTRYLEN(idx, col, res) \
+         (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
++#define NISOBJVAL(col, obj) \
++  ((obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
++
++#define NISOBJLEN(col, obj) \
++  ((obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
++
+ int
+-_nss_nisplus_parse_pwent_chk (nis_result *result, struct passwd *pw,
+-                            char *buffer, size_t buflen, int *errnop)
++_nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw,
++                        char *buffer, size_t buflen, int *errnop)
+ {
+   if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+       || NIS_RES_NUMOBJ (result) != 1
+@@ -43,19 +49,12 @@ _nss_nisplus_parse_pwent_chk (nis_result
+       || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 7)
+     return 0;
+-  return _nss_nisplus_parse_pwent (result, 0, pw, buffer, buflen, errnop);
+-}
+-
+-
+-int
+-_nss_nisplus_parse_pwent (nis_result *result, size_t entry, struct passwd *pw,
+-                        char *buffer, size_t buflen, int *errnop)
+-{
++  nis_object *obj = NIS_RES_OBJECT (result);
+   char *first_unused = buffer;
+   size_t room_left = buflen;
+   size_t len;
+-  if (NISENTRYLEN (entry, 0, result) >= room_left)
++  if (NISOBJLEN (0, obj) >= room_left)
+     {
+       /* The line is too long for our buffer.  */
+     no_more_room:
+@@ -63,9 +62,8 @@ _nss_nisplus_parse_pwent (nis_result *re
+       return -1;
+     }
+-  strncpy (first_unused, NISENTRYVAL (entry, 0, result),
+-         NISENTRYLEN (entry, 0, result));
+-  first_unused[NISENTRYLEN (entry, 0, result)] = '\0';
++  strncpy (first_unused, NISOBJVAL (0, obj), NISOBJLEN (0, obj));
++  first_unused[NISOBJLEN (0, obj)] = '\0';
+   len = strlen (first_unused);
+   if (len == 0) /* No name ? Should never happen, database is corrupt */
+     return 0;
+@@ -73,19 +71,18 @@ _nss_nisplus_parse_pwent (nis_result *re
+   room_left -= len + 1;
+   first_unused += len + 1;
+-  if (NISENTRYLEN (entry, 1, result) >= room_left)
++  if (NISOBJLEN (1, obj) >= room_left)
+     goto no_more_room;
+-  strncpy (first_unused, NISENTRYVAL (entry, 1, result),
+-         NISENTRYLEN (entry, 1, result));
+-  first_unused[NISENTRYLEN (entry, 1, result)] = '\0';
++  strncpy (first_unused, NISOBJVAL (1, obj), NISOBJLEN (1, obj));
++  first_unused[NISOBJLEN (1, obj)] = '\0';
+   pw->pw_passwd = first_unused;
+   len = strlen (first_unused);
+   room_left -= len + 1;
+   first_unused += len + 1;
+-  char *numstr = NISENTRYVAL (entry, 2, result);
+-  len = NISENTRYLEN (entry, 2, result);
++  char *numstr = NISOBJVAL (2, obj);
++  len = NISOBJLEN (2, obj);
+   if (len == 0 && numstr[len - 1] != '\0')
+     {
+       if (len >= room_left)
+@@ -100,8 +97,8 @@ _nss_nisplus_parse_pwent (nis_result *re
+     return 0;
+   pw->pw_uid = strtoul (numstr, NULL, 10);
+-  numstr = NISENTRYVAL (entry, 3, result);
+-  len = NISENTRYLEN (entry, 3, result);
++  numstr = NISOBJVAL (3, obj);
++  len = NISOBJLEN (3, obj);
+   if (len == 0 && numstr[len - 1] != '\0')
+     {
+       if (len >= room_left)
+@@ -116,34 +113,31 @@ _nss_nisplus_parse_pwent (nis_result *re
+     return 0;
+   pw->pw_gid = strtoul (numstr, NULL, 10);
+-  if (NISENTRYLEN(entry, 4, result) >= room_left)
++  if (NISOBJLEN(4, obj) >= room_left)
+     goto no_more_room;
+-  strncpy (first_unused, NISENTRYVAL (entry, 4, result),
+-         NISENTRYLEN (entry, 4, result));
+-  first_unused[NISENTRYLEN (entry, 4, result)] = '\0';
++  strncpy (first_unused, NISOBJVAL (4, obj), NISOBJLEN (4, obj));
++  first_unused[NISOBJLEN (4, obj)] = '\0';
+   pw->pw_gecos = first_unused;
+   len = strlen (first_unused);
+   room_left -= len + 1;
+   first_unused += len + 1;
+-  if (NISENTRYLEN (entry, 5, result) >= room_left)
++  if (NISOBJLEN (5, obj) >= room_left)
+     goto no_more_room;
+-  strncpy (first_unused, NISENTRYVAL (entry, 5, result),
+-         NISENTRYLEN (entry, 5, result));
+-  first_unused[NISENTRYLEN (entry, 5, result)] = '\0';
++  strncpy (first_unused, NISOBJVAL (5, obj), NISOBJLEN (5, obj));
++  first_unused[NISOBJLEN (5, obj)] = '\0';
+   pw->pw_dir = first_unused;
+   len = strlen (first_unused);
+   room_left -= len + 1;
+   first_unused += len + 1;
+-  if (NISENTRYLEN (entry, 6, result) >= room_left)
++  if (NISOBJLEN (6, obj) >= room_left)
+     goto no_more_room;
+-  strncpy (first_unused, NISENTRYVAL (entry, 6, result),
+-         NISENTRYLEN (entry, 6, result));
+-  first_unused[NISENTRYLEN (entry, 6, result)] = '\0';
++  strncpy (first_unused, NISOBJVAL (6, obj), NISOBJLEN (6, obj));
++  first_unused[NISOBJLEN (6, obj)] = '\0';
+   pw->pw_shell = first_unused;
+   len = strlen (first_unused);
+   room_left -= len + 1;
+@@ -154,26 +148,23 @@ _nss_nisplus_parse_pwent (nis_result *re
+ int
+-_nss_nisplus_parse_grent (nis_result *result, u_long entry, struct group *gr,
++_nss_nisplus_parse_grent (nis_result *result, struct group *gr,
+                         char *buffer, size_t buflen, int *errnop)
+ {
++  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
++      || __type_of(NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
++      || strcmp (NIS_RES_OBJECT (result)[0].EN_data.en_type, "group_tbl") != 0
++      || NIS_RES_OBJECT (result)[0].EN_data.en_cols.en_cols_len < 4)
++    return 0;
++
++  nis_object *obj = NIS_RES_OBJECT (result);
+   char *first_unused = buffer;
+   size_t room_left = buflen;
+   char *line;
+   int count;
+   size_t len;
+-  if (result == NULL)
+-    return 0;
+-
+-  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+-      || __type_of(NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
+-      || strcmp (NIS_RES_OBJECT (result)[entry].EN_data.en_type,
+-               "group_tbl") != 0
+-      || NIS_RES_OBJECT (result)[entry].EN_data.en_cols.en_cols_len < 4)
+-    return 0;
+-
+-  if (NISENTRYLEN (entry, 0, result) >= room_left)
++  if (NISOBJLEN (0, obj) >= room_left)
+     {
+       /* The line is too long for our buffer.  */
+     no_more_room:
+@@ -181,9 +172,8 @@ _nss_nisplus_parse_grent (nis_result *re
+       return -1;
+     }
+-  strncpy (first_unused, NISENTRYVAL (entry, 0, result),
+-         NISENTRYLEN (entry, 0, result));
+-  first_unused[NISENTRYLEN (entry, 0, result)] = '\0';
++  strncpy (first_unused, NISOBJVAL (0, obj), NISOBJLEN (0, obj));
++  first_unused[NISOBJLEN (0, obj)] = '\0';
+   len = strlen (first_unused);
+   if (len == 0) /* group table is corrupt */
+     return 0;
+@@ -191,20 +181,19 @@ _nss_nisplus_parse_grent (nis_result *re
+   room_left -= len + 1;
+   first_unused += len + 1;
+-  if (NISENTRYLEN (entry, 1, result) >= room_left)
++  if (NISOBJLEN (1, obj) >= room_left)
+     goto no_more_room;
+-  strncpy (first_unused, NISENTRYVAL (entry, 1, result),
+-         NISENTRYLEN (entry, 1, result));
+-  first_unused[NISENTRYLEN (entry, 1, result)] = '\0';
++  strncpy (first_unused, NISOBJVAL (1, obj), NISOBJLEN (1, obj));
++  first_unused[NISOBJLEN (1, obj)] = '\0';
+   gr->gr_passwd = first_unused;
+   len = strlen (first_unused);
+   room_left -= len + 1;
+   first_unused += len + 1;
+-  char *numstr = NISENTRYVAL (entry, 2, result);
+-  len = NISENTRYLEN (entry, 2, result);
+-  if (len == 0 && numstr[len - 1] != '\0')
++  char *numstr = NISOBJVAL (2, obj);
++  len = NISOBJLEN (2, obj);
++  if (len == 0 || numstr[len - 1] != '\0')
+     {
+       if (len >= room_left)
+       goto no_more_room;
+@@ -218,12 +207,11 @@ _nss_nisplus_parse_grent (nis_result *re
+     return 0;
+   gr->gr_gid = strtoul (numstr, NULL, 10);
+-  if (NISENTRYLEN (entry, 3, result) >= room_left)
++  if (NISOBJLEN (3, obj) >= room_left)
+     goto no_more_room;
+-  strncpy (first_unused, NISENTRYVAL (entry, 3, result),
+-         NISENTRYLEN (entry, 3, result));
+-  first_unused[NISENTRYLEN (entry, 3, result)] = '\0';
++  strncpy (first_unused, NISOBJVAL (3, obj), NISOBJLEN (3, obj));
++  first_unused[NISOBJLEN (3, obj)] = '\0';
+   line = first_unused;
+   len = strlen (line);
+   room_left -= len + 1;
+--- libc/nis/nss_nisplus/nisplus-pwd.c 29 Apr 2006 20:19:09 -0000      1.22
++++ libc/nis/nss_nisplus/nisplus-pwd.c 20 May 2006 19:20:19 -0000      1.23
+@@ -29,16 +29,21 @@
+ #include "nss-nisplus.h"
+ #include "nisplus-parser.h"
+ #include <libnsl.h>
++#include <nis_intern.h>
++#include <nis_xdr.h>
+ __libc_lock_define_initialized (static, lock)
+-/* Previous result of iteration.  */
+-static nis_result *result;
++/* Connection information.  */
++static ib_request *ibreq;
++static directory_obj *dir;
++static dir_binding bptr;
++static char *tablepath;
++static char *tableptr;
++/* Cursor.  */
++static netobj cursor;
+-/* All results of batch table load.  */
+-static nis_result *cached_results;
+-static size_t cached_results_iter;
+ nis_name pwd_tablename_val attribute_hidden;
+ size_t pwd_tablename_len attribute_hidden;
+@@ -80,50 +85,48 @@ _nss_pwd_create_tablename (int *errnop)
+ static void
+ internal_nisplus_endpwent (void)
+ {
+-  if (cached_results != NULL)
+-    {
+-      nis_freeresult (cached_results);
+-      cached_results = NULL;
+-      cached_results_iter = 0;
+-    }
++  __nisbind_destroy (&bptr);
++  memset (&bptr, '\0', sizeof (bptr));
+-  if (result != NULL)
+-    {
+-      nis_freeresult (result);
+-      result = NULL;
+-    }
++  nis_free_directory (dir);
++  dir = NULL;
++
++  nis_free_request (ibreq);
++  ibreq = NULL;
++
++  xdr_free ((xdrproc_t) xdr_netobj, (char *) &cursor);
++  memset (&cursor, '\0', sizeof (cursor));
++
++  free (tablepath);
++  tableptr = tablepath = NULL;
+ }
+ static enum nss_status
+ internal_nisplus_setpwent (int *errnop)
+ {
+-  enum nss_status status;
++  enum nss_status status = NSS_STATUS_SUCCESS;
+-  cached_results = nis_list (pwd_tablename_val, FOLLOW_PATH | FOLLOW_LINKS,
+-                           NULL, NULL);
++  if (pwd_tablename_val == NULL)
++    status = _nss_pwd_create_tablename (errnop);
+-  if (cached_results == NULL)
++  if (status == NSS_STATUS_SUCCESS)
+     {
+-      *errnop = errno;
+-      status = NSS_STATUS_TRYAGAIN;
+-    }
+-  else if (__builtin_expect ((status = niserr2nss (cached_results->status))
+-                           != NSS_STATUS_SUCCESS, 0))
+-    {
+-      nis_freeresult (cached_results);
+-      cached_results = NULL;
+-    }
+-  else if (__builtin_expect (__type_of (NIS_RES_OBJECT (cached_results))
+-                           != NIS_ENTRY_OBJ
+-                           || strcmp (NIS_RES_OBJECT (cached_results)->EN_data.en_type,
+-                                      "passwd_tbl") != 0
+-                           || NIS_RES_OBJECT (cached_results)->EN_data.en_cols.en_cols_len < 7,
+-                           0))
+-    {
+-      nis_freeresult (cached_results);
+-      cached_results = NULL;
+-      status = NSS_STATUS_NOTFOUND;
++      ibreq = __create_ib_request (pwd_tablename_val, 0);
++      if (ibreq == NULL)
++      {
++        *errnop = errno;
++        return NSS_STATUS_TRYAGAIN;
++      }
++
++      nis_error retcode = __prepare_niscall (pwd_tablename_val, &dir,
++                                           &bptr, 0);
++      if (retcode != NIS_SUCCESS)
++      {
++        nis_free_request (ibreq);
++        ibreq = NULL;
++        status = niserr2nss (retcode);
++      }
+     }
+   return status;
+@@ -133,26 +136,15 @@ internal_nisplus_setpwent (int *errnop)
+ enum nss_status
+ _nss_nisplus_setpwent (int stayopen)
+ {
+-  enum nss_status status = NSS_STATUS_SUCCESS;
++  enum nss_status status;
+   __libc_lock_lock (lock);
+   internal_nisplus_endpwent ();
+-  if (pwd_tablename_val == NULL)
+-    {
+-      // XXX We need to be able to set errno.  Pass in new parameter.
+-      int err;
+-      status = _nss_pwd_create_tablename (&err);
+-    }
+-
+-  if (status == NSS_STATUS_SUCCESS
+-      && (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ))
+-    {
+-      // XXX We need to be able to set errno.  Pass in new parameter.
+-      int err;
+-      status = internal_nisplus_setpwent (&err);
+-    }
++  // XXX We need to be able to set errno.  Pass in new parameter.
++  int err;
++  status = internal_nisplus_setpwent (&err);
+   __libc_lock_unlock (lock);
+@@ -178,98 +170,104 @@ internal_nisplus_getpwent_r (struct pass
+                            int *errnop)
+ {
+   int parse_res = -1;
+-  nis_result *saved_res = NULL;
++  enum nss_status retval = NSS_STATUS_SUCCESS;
+   /* Get the next entry until we found a correct one. */
+   do
+     {
+-      if (cached_results != NULL)
++      nis_error status;
++      nis_result result;
++      memset (&result, '\0', sizeof (result));
++
++      if (cursor.n_bytes == NULL)
+       {
+-      handle_batch_read:
+-        /* See whether we reported the last problem.  */
+-        if (cached_results_iter >= NIS_RES_NUMOBJ (cached_results))
+-          return NSS_STATUS_NOTFOUND;
+-
+-        parse_res = _nss_nisplus_parse_pwent (cached_results,
+-                                              cached_results_iter, pw,
+-                                              buffer, buflen, errnop);
++        if (ibreq == NULL)
++          {
++            retval = internal_nisplus_setpwent (errnop);
++            if (retval != NSS_STATUS_SUCCESS)
++              return retval;
++          }
++
++        status = __do_niscall3 (&bptr, NIS_IBFIRST,
++                                (xdrproc_t) _xdr_ib_request,
++                                (caddr_t) ibreq,
++                                (xdrproc_t) _xdr_nis_result,
++                                (caddr_t) &result,
++                                0, NULL);
+       }
+       else
+       {
+-        if (result == NULL)
+-          {
+-            if (pwd_tablename_val == NULL)
+-              {
+-                enum nss_status status = _nss_pwd_create_tablename (errnop);
+-
+-                if (status != NSS_STATUS_SUCCESS)
+-                  return status;
+-              }
+-
+-            /* Determine whether we should instead read all entries at
+-               once.  */
+-            if (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
+-              {
+-                enum nss_status status = internal_nisplus_setpwent (errnop);
+-
+-                if (status == NSS_STATUS_SUCCESS && cached_results != NULL)
+-                  goto handle_batch_read;
+-              }
+-
+-            saved_res = NULL;
+-
+-            result = nis_first_entry (pwd_tablename_val);
+-            if (result == NULL)
+-              {
+-                *errnop = errno;
+-                return NSS_STATUS_TRYAGAIN;
+-              }
+-            if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+-              return niserr2nss (result->status);
+-          }
+-        else
+-          {
+-            saved_res = result;
+-            result = nis_next_entry (pwd_tablename_val, &result->cookie);
+-            if (result == NULL)
+-              {
+-                *errnop = errno;
+-                return NSS_STATUS_TRYAGAIN;
+-              }
+-            if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+-              {
+-                nis_freeresult (saved_res);
+-                return niserr2nss (result->status);
+-              }
+-          }
++        ibreq->ibr_cookie.n_bytes = cursor.n_bytes;
++        ibreq->ibr_cookie.n_len = cursor.n_len;
+-        parse_res = _nss_nisplus_parse_pwent_chk (result, pw, buffer,
+-                                                  buflen, errnop);
++        status = __do_niscall3 (&bptr, NIS_IBNEXT,
++                                (xdrproc_t) _xdr_ib_request,
++                                (caddr_t) ibreq,
++                                (xdrproc_t) _xdr_nis_result,
++                                (caddr_t) &result,
++                                0, NULL);
++
++        ibreq->ibr_cookie.n_bytes = NULL;
++        ibreq->ibr_cookie.n_len = 0;
++      }
++
++      if (status != NIS_SUCCESS)
++      return niserr2nss (status);
++
++      if (NIS_RES_STATUS (&result) == NIS_NOTFOUND)
++      {
++        /* No more entries on this server.  This means we have to go
++           to the next server on the path.  */
++        status = __follow_path (&tablepath, &tableptr, ibreq, &bptr);
++        if (status != NIS_SUCCESS)
++          return niserr2nss (status);
++
++        directory_obj *newdir = NULL;
++        dir_binding newbptr;
++        status = __prepare_niscall (ibreq->ibr_name, &newdir, &newbptr, 0);
++        if (status != NIS_SUCCESS)
++          return niserr2nss (status);
++
++        nis_free_directory (dir);
++        dir = newdir;
++        __nisbind_destroy (&bptr);
++        bptr = newbptr;
++
++        xdr_free ((xdrproc_t) xdr_netobj, (char *) &result.cookie);
++        result.cookie.n_bytes = NULL;
++        result.cookie.n_len = 0;
++        parse_res = 0;
++        goto next;
+       }
++      else if (NIS_RES_STATUS (&result) != NIS_SUCCESS)
++      return niserr2nss (NIS_RES_STATUS (&result));
++
++      parse_res = _nss_nisplus_parse_pwent (&result, pw, buffer,
++                                          buflen, errnop);
+       if (__builtin_expect (parse_res == -1, 0))
+       {
+-        if (cached_results == NULL)
+-          {
+-            nis_freeresult (result);
+-            result = saved_res;
+-          }
+         *errnop = ERANGE;
+-        return NSS_STATUS_TRYAGAIN;
++        retval = NSS_STATUS_TRYAGAIN;
++        goto freeres;
+       }
+-      if (cached_results != NULL)
+-      ++cached_results_iter;
+-      else
+-      if (saved_res)
+-        {
+-          nis_freeresult (saved_res);
+-          saved_res = NULL;
+-        }
++    next:
++      /* Free the old cursor.  */
++      xdr_free ((xdrproc_t) xdr_netobj, (char *) &cursor);
++      /* Remember the new one.  */
++      cursor.n_bytes = result.cookie.n_bytes;
++      cursor.n_len = result.cookie.n_len;
++      /* Free the result structure.  NB: we do not remove the cookie.  */
++      result.cookie.n_bytes = NULL;
++      result.cookie.n_len = 0;
++    freeres:
++      xdr_free ((xdrproc_t) _xdr_nis_result, (char *) &result);
++      memset (&result, '\0', sizeof (result));
+     }
+   while (!parse_res);
+-  return NSS_STATUS_SUCCESS;
++  return retval;
+ }
+ enum nss_status
+@@ -331,8 +329,7 @@ _nss_nisplus_getpwnam_r (const char *nam
+       return status;
+     }
+-  parse_res = _nss_nisplus_parse_pwent_chk (result, pw, buffer, buflen,
+-                                          errnop);
++  parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop);
+   nis_freeresult (result);
+@@ -391,8 +388,7 @@ _nss_nisplus_getpwuid_r (const uid_t uid
+       return status;
+     }
+-  parse_res = _nss_nisplus_parse_pwent_chk (result, pw, buffer, buflen,
+-                                          errnop);
++  parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop);
+   nis_freeresult (result);
diff --git a/src/patches/glibc/glibc-nis+.patch b/src/patches/glibc/glibc-nis+.patch
new file mode 100644 (file)
index 0000000..c118fa2
--- /dev/null
@@ -0,0 +1,4601 @@
+2006-03-24  Jakub Jelinek  <jakub@redhat.com>
+
+       * nis/nss_nisplus/nisplus-proto.c (_nss_create_tablename): Check the
+       return value of malloc rather than the static var again.
+       * nis/nss_nisplus/nisplus-grp.c (_nss_create_tablename): Likewise.
+       * nis/nss_nisplus/nisplus-network.c (_nss_create_tablename): Likewise.
+       * nis/nss_nisplus/nisplus-ethers.c (_nss_create_tablename): Likewise.
+       * nis/nss_nisplus/nisplus-rpc.c (_nss_create_tablename): Likewise.
+       * nis/nss_nisplus/nisplus-service.c (_nss_create_tablename): Likewise.
+       * nis/nss_nisplus/nisplus-hosts.c (_nss_create_tablename): Likewise.
+       * nis/nss_nisplus/nisplus-alias.c (_nss_create_tablename): Likewise.
+       * nis/nss_nisplus/nisplus-pwd.c (_nss_pwd_create_tablename): Likewise.
+
+2006-02-22  Jakub Jelinek  <jakub@redhat.com>
+
+       * nis/ypclnt.c (yperr_string, ypbinderr_string): Add N_()
+       around string literals.
+
+2005-12-08  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_call.c (inetstr2int): Optimize.
+
+2005-12-08  Jakub Jelinek  <jakub@redhat.com>
+
+       * nis/nis_call.c (__nisbind_create): Remove __nisbind_destroy,
+       ->clnt cannot be != NULL.
+       (__do_niscall): No need to use __nisbind_destroy, __nisbind_next
+       did it.
+       (__nisbind_connect): use_auth is already TRUE, otherwise we would
+       not be here.
+
+       * nis/nis_lookup.c (nis_lookup): Remove unnecessary
+       __nisbind_destroy calls.  __nisbind_next does all that.
+
+       * nis/ypclnt.c (yp_update): Before trying default authentication,
+       free DES descriptor.
+
+2005-12-07  Jakub Jelinek  <jakub@redhat.com>
+
+       * nis/nis_table.c (nis_list): Fix memory handling in error case.
+
+2005-12-07  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_table.c (nis_list): Remove have_tablepath, just use the
+       pointer value itself.
+
+       * sunrpc/auth_des.c (authdes_pk_create): If conversation key
+       cannot be created, free memory.
+       Reported by rprasad@vmware.com.
+
+2005-12-03  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_table.c (nis_list): Optimize freeing and reallocation of
+       result record.
+
+       * nis/nss_nisplus/nisplus-network.c (_nss_nisplus_getnetbyaddr_r):
+       Better sized buffers.  Correct error case handling.
+       * nis/nis_error.c (nis_sperror_r): Let snprintf determine whether
+       there is an overflow.
+       * nis/nss_nisplus/nisplus-service.c: Fix locking to use
+       _nss_create_tablename.  Avoid unnecessary copying, remove
+       unnecessary variables, general cleanup.
+       * nis/nss_nisplus/nisplus-rpc.c: Likewise.
+       * nis/nss_nisplus/nisplus-proto.c: Likewise..
+       * nis/nss_nisplus/nisplus-network.c: Fix locking to use
+       _nss_create_tablename.  Avoid unnecessary copying, general cleanup.
+       * nis/nss_nisplus/nisplus-hosts.c (_nss_nisplus_getipnodebyname_r):
+       Removed.
+       Fix locking to use _nss_create_tablename.  Avoid unnecessary copying,
+       general cleanup.
+       * nis/nss_nisplus/nisplus-ethers.c (_nss_nisplus_getntohost_r):
+       Correctly construct request.
+       Fix locking to use _nss_create_tablename.  Avoid unnecessary copying,
+       general cleanup.
+       * nis/nss_nisplus/nisplus-alias.c: Fix locking to use
+       _nss_create_tablename.  Avoid unnecessary copying, general cleanup.
+       * nis/nss_nisplus/nisplus-netgrp.c (_nss_nisplus_setnetgrent):
+       Rewrite to use snprintf.
+       * nis/nss_nisplus/nisplus-publickey.c (_nss_nisplus_netname2user):
+       Likewise.
+
+2005-12-02  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nss_nisplus/nisplus-pwd.c (_nss_pwd_create_tablename):
+       Renamed from _nss_create_tablename.  Export from file (but not DSO).
+       (pwd_tablename_val): Renamed from tablename_val, mark hidden.
+       (pwd_tablename_len): Renamed from tablename_len, mark hidden.
+       Change all users.
+       * nis/nss_nisplus/nisplus-spwd.c (_nss_create_tablename): Removed.
+       Use _nss_pwd_create_tablename now.  Use pwd_tablename_val and
+       pwd_tablename_len.  Remove unnecessary variables, general cleanup.
+
+       * nis/nss_nisplus/nisplus-pwd.c: Fix locking to use
+       _nss_create_tablename.  Avoid unnecessary copying, remove
+       unnecessary variables, general cleanup.
+       * nis/nss_nisplus/nisplus-grp.c: Likewise.
+
+2005-11-27  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_table.c (nis_list): Add more free calls in error cases.
+
+2005-11-26  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_lookup.c (nis_lookup): Mark RPCTIMEOUT as const.  Pretty
+       printing.
+
+       * nis/nis_table.c (__create_ib_request): Use strdupa instead of
+       variable size array.
+       (RPCTIMEOUT): Mark as const.
+
+       * nis/ypclnt.c (yp_bind_ypbindprog): Initialize clnt_saddr by hand.
+       (ypdomainname): Renamed from __ypdomainname.  No need for initializer.
+       (ypbindlist): Renamed from __ypbindlist.
+       (yperr_string): Reduce size of function by using only one gettext call.
+       (ypbinderr_string): Likewise.
+       (yp_match): Free response in case memory for return value cannot be
+       allocated.
+       (yp_first): Likewise.
+       (yp_next): Likewise.
+       (do_ypcall_tr): New function which translates error codes as well.
+       (yp_match, yp_next, yp_master, yp_order, yp_maplist): Use it.
+       (yp_all): Correct test for invalid parameter.
+       Pretty printing.
+       (RPCTIMEOUT, UDPTIMEOUT): Mark as const.
+
+--- libc/nis/nis_call.c        26 Oct 2004 01:14:11 -0000      1.32
++++ libc/nis/nis_call.c        9 Dec 2005 06:47:59 -0000       1.36
+@@ -40,25 +40,16 @@ extern u_short __pmap_getnisport (struct
+ unsigned long
+ inetstr2int (const char *str)
+ {
+-  char buffer[strlen (str) + 3];
+-  size_t buflen;
+-  size_t i, j;
+-
+-  buflen = stpcpy (buffer, str) - buffer;
+-
+-  j = 0;
+-  for (i = 0; i < buflen; ++i)
+-    if (buffer[i] == '.')
++  size_t j = 0;
++  for (size_t i = 0; str[i] != '\0'; ++i)
++    if (str[i] == '.' && ++j == 4)
+       {
+-      ++j;
+-      if (j == 4)
+-        {
+-          buffer[i] = '\0';
+-          break;
+-        }
++      char buffer[i + 1];
++      buffer[i] = '\0';
++      return inet_addr (memcpy (buffer, str, i));
+       }
+-  return inet_addr (buffer);
++  return inet_addr (str);
+ }
+ void
+@@ -179,7 +170,6 @@ __nisbind_connect (dir_binding *dbp)
+       }
+       else
+       dbp->clnt->cl_auth = authunix_create_default ();
+-      dbp->use_auth = TRUE;
+     }
+   return NIS_SUCCESS;
+@@ -215,10 +205,7 @@ __nisbind_create (dir_binding *dbp, cons
+   dbp->class = -1;
+   if (__nis_findfastest (dbp) < 1)
+-    {
+-      __nisbind_destroy (dbp);
+-      return NIS_NAMEUNREACHABLE;
+-    }
++    return NIS_NAMEUNREACHABLE;
+   return NIS_SUCCESS;
+ }
+@@ -585,7 +572,6 @@ __do_niscall (const_nis_name name, u_lon
+         if (__nisbind_next (&bptr) != NIS_SUCCESS)
+           {
+             nis_free_directory (dir);
+-            __nisbind_destroy (&bptr);
+             return NIS_NAMEUNREACHABLE;
+           }
+       }
+--- libc/nis/nis_error.c       24 Oct 2004 20:28:28 -0000      1.11
++++ libc/nis/nis_error.c       3 Dec 2005 22:15:00 -0000       1.12
+@@ -102,26 +102,21 @@ char *
+ nis_sperror_r (const nis_error status, const char *label,
+              char *buffer, size_t buflen)
+ {
+-  const char *cptr;
+-
+-  cptr = nis_sperrno (status);
+-
+-  if ((strlen (cptr) + strlen (label) + 3) > buflen)
++  if (snprintf (buffer, buflen, "%s: %s", label, nis_sperrno (status))
++      >= buflen)
+     {
+       errno = ERANGE;
+       return NULL;
+     }
+-    sprintf (buffer, "%s: %s", label, cptr);
+-
+-    return buffer;
++  return buffer;
+ }
+ libnsl_hidden_def (nis_sperror_r)
+ char *
+ nis_sperror (const nis_error status, const char *label)
+ {
+-  static char buffer[NIS_MAXNAMELEN +1];
++  static char buffer[NIS_MAXNAMELEN + 1];
+   return nis_sperror_r (status, label, buffer, sizeof (buffer));
+ }
+--- libc/nis/nis_lookup.c      24 Oct 2004 20:28:28 -0000      1.14
++++ libc/nis/nis_lookup.c      8 Dec 2005 20:19:11 -0000       1.16
+@@ -81,7 +81,6 @@ nis_lookup (const_nis_name name, const u
+       {
+         if (__nisbind_next (&bptr) != NIS_SUCCESS)
+           {
+-            __nisbind_destroy (&bptr);
+             nis_free_directory (dir);
+             NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
+             return res;
+@@ -90,7 +89,7 @@ nis_lookup (const_nis_name name, const u
+       do
+       {
+-        static struct timeval RPCTIMEOUT = {10, 0};
++        static const struct timeval RPCTIMEOUT = {10, 0};
+         enum clnt_stat result;
+       again:
+@@ -107,8 +106,8 @@ nis_lookup (const_nis_name name, const u
+             if (NIS_RES_STATUS (res) == NIS_SUCCESS)
+               {
+-                  if (__type_of(NIS_RES_OBJECT (res)) == NIS_LINK_OBJ &&
+-                      flags & FOLLOW_LINKS) /* We are following links */
++                  if (__type_of(NIS_RES_OBJECT (res)) == NIS_LINK_OBJ
++                      && (flags & FOLLOW_LINKS)) /* We are following links */
+                     {
+                       if (count_links)
+                         free (req.ns_name);
+@@ -137,16 +136,17 @@ nis_lookup (const_nis_name name, const u
+                     }
+               }
+             else
+-              if ((NIS_RES_STATUS (res) == NIS_SYSTEMERROR) ||
+-                  (NIS_RES_STATUS (res) == NIS_NOSUCHNAME) ||
+-                  (NIS_RES_STATUS (res) == NIS_NOT_ME))
++              if (NIS_RES_STATUS (res) == NIS_SYSTEMERROR
++                  || NIS_RES_STATUS (res) == NIS_NOSUCHNAME
++                  || NIS_RES_STATUS (res) == NIS_NOT_ME)
+                 {
+                   if (link_first_try)
+                     {
+                       __nisbind_destroy (&bptr);
+                       nis_free_directory (dir);
+-                      if (__nisfind_server (req.ns_name, &dir) != NIS_SUCCESS)
++                      if (__nisfind_server (req.ns_name, &dir)
++                          != NIS_SUCCESS)
+                         return res;
+                       if (__nisbind_create (&bptr,
+@@ -166,7 +166,6 @@ nis_lookup (const_nis_name name, const u
+                     {
+                       if (__nisbind_next (&bptr) != NIS_SUCCESS)
+                         {
+-                          __nisbind_destroy (&bptr);
+                           nis_free_directory (dir);
+                           return res;
+                         }
+--- libc/nis/nis_table.c       29 Apr 2005 09:16:12 -0000      1.24
++++ libc/nis/nis_table.c       8 Dec 2005 04:11:05 -0000       1.30
+@@ -27,11 +27,9 @@
+ static struct ib_request *
+ __create_ib_request (const_nis_name name, unsigned int flags)
+ {
+-  struct ib_request *ibreq = calloc (1, sizeof (ib_request));
+-  char buf[strlen (name) + 1];
++  struct ib_request *ibreq = calloc (1, sizeof (struct ib_request));
+   nis_attr *search_val = NULL;
+   size_t search_len = 0;
+-  char *cptr;
+   size_t size = 0;
+   if (ibreq == NULL)
+@@ -39,7 +37,7 @@ __create_ib_request (const_nis_name name
+   ibreq->ibr_flags = flags;
+-  cptr = strcpy (buf, name);
++  char *cptr = strdupa (name);
+   /* Not of "[key=value,key=value,...],foo.." format? */
+   if (cptr[0] != '[')
+@@ -49,8 +47,8 @@ __create_ib_request (const_nis_name name
+   ibreq->ibr_name = strchr (cptr, ']');
+   if (ibreq->ibr_name == NULL || ibreq->ibr_name[1] != ',')
+     {
+-      ibreq->ibr_name = NULL; /* Or the xdr_* functions will dump */
+-      nis_free_request (ibreq);
++      /* The object has not really been built yet so we use free.  */
++      free (ibreq);
+       return NULL;
+     }
+@@ -120,17 +118,16 @@ __create_ib_request (const_nis_name name
+   return ibreq;
+ }
+-static struct timeval RPCTIMEOUT = {10, 0};
++static const struct timeval RPCTIMEOUT = {10, 0};
+ static char *
+ __get_tablepath (char *name, dir_binding *bptr)
+ {
+   enum clnt_stat result;
+-  nis_result *res = calloc (1, sizeof (nis_result));
++  nis_result res;
+   struct ns_request req;
+-  if (res == NULL)
+-    return NULL;
++  memset (&res, '\0', sizeof (res));
+   req.ns_name = name;
+   req.ns_object.ns_object_len = 0;
+@@ -138,20 +135,16 @@ __get_tablepath (char *name, dir_binding
+   result = clnt_call (bptr->clnt, NIS_LOOKUP, (xdrproc_t) _xdr_ns_request,
+                     (caddr_t) &req, (xdrproc_t) _xdr_nis_result,
+-                    (caddr_t) res, RPCTIMEOUT);
++                    (caddr_t) &res, RPCTIMEOUT);
+-  if (result == RPC_SUCCESS && NIS_RES_STATUS (res) == NIS_SUCCESS &&
+-      __type_of (NIS_RES_OBJECT (res)) == NIS_TABLE_OBJ)
+-    {
+-      char *cptr = strdup (NIS_RES_OBJECT (res)->TA_data.ta_path);
+-      nis_freeresult (res);
+-      return cptr;
+-    }
++  const char *cptr;
++  if (result == RPC_SUCCESS && NIS_RES_STATUS (&res) == NIS_SUCCESS
++      && __type_of (NIS_RES_OBJECT (&res)) == NIS_TABLE_OBJ)
++    cptr = NIS_RES_OBJECT (&res)->TA_data.ta_path;
+   else
+-    {
+-      nis_freeresult (res);
+-      return strdup ("");
+-    }
++    cptr = "";
++
++  return strdup (cptr);
+ }
+ nis_result *
+@@ -171,8 +164,8 @@ nis_list (const_nis_name name, unsigned 
+   nis_name namebuf[2] = {NULL, NULL};
+   int name_nr = 0;
+   nis_cb *cb = NULL;
+-  char *tableptr, *tablepath = NULL;
+-  int have_tablepath = 0;
++  char *tableptr;
++  char *tablepath = NULL;
+   int first_try = 0; /* Do we try the old binding at first ? */
+   if (res == NULL)
+@@ -205,6 +198,7 @@ nis_list (const_nis_name name, unsigned 
+       ibreq->ibr_name = strdup (names[name_nr]);
+       if (ibreq->ibr_name == NULL)
+       {
++        nis_freenames (names);
+         nis_free_request (ibreq);
+         NIS_RES_STATUS (res) = NIS_NOMEMORY;
+         return res;
+@@ -227,30 +221,24 @@ nis_list (const_nis_name name, unsigned 
+       status = __nisfind_server (ibreq->ibr_name, &dir);
+       if (status != NIS_SUCCESS)
+-        {
+-        nis_free_request (ibreq);
++      {
+           NIS_RES_STATUS (res) = status;
+-          return res;
+-        }
++          goto fail3;
++      }
+       status = __nisbind_create (&bptr, dir->do_servers.do_servers_val,
+-                                 dir->do_servers.do_servers_len, flags);
++                               dir->do_servers.do_servers_len, flags);
+       if (status != NIS_SUCCESS)
+         {
+-        nis_free_request (ibreq);
+           NIS_RES_STATUS (res) = status;
+-          nis_free_directory (dir);
+-          return res;
++        goto fail2;
+         }
+       while (__nisbind_connect (&bptr) != NIS_SUCCESS)
+       if (__nisbind_next (&bptr) != NIS_SUCCESS)
+         {
+-          __nisbind_destroy (&bptr);
+-          nis_free_directory (dir);
+-          nis_free_request (ibreq);
+           NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
+-          return res;
++          goto fail;
+         }
+       if (callback != NULL)
+@@ -274,8 +262,8 @@ nis_list (const_nis_name name, unsigned 
+         case NIS_PARTIAL:
+         case NIS_SUCCESS:
+         case NIS_S_SUCCESS:
+-          if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ &&
+-              flags & FOLLOW_LINKS)           /* We are following links.  */
++          if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ
++              && (flags & FOLLOW_LINKS))      /* We are following links.  */
+             {
+               free (ibreq->ibr_name);
+               ibreq->ibr_name = NULL;
+@@ -291,8 +279,22 @@ nis_list (const_nis_name name, unsigned 
+                 strdup (NIS_RES_OBJECT (res)->LI_data.li_name);
+               if (ibreq->ibr_name == NULL)
+                 {
+-                  nis_free_request (ibreq);
+                   NIS_RES_STATUS (res) = NIS_NOMEMORY;
++                fail:
++                  __nisbind_destroy (&bptr);
++                fail2:
++                  nis_free_directory (dir);
++                fail3:
++                  free (tablepath);
++                  if (cb)
++                    {
++                      __nis_destroy_callback (cb);
++                      ibreq->ibr_cbhost.ibr_cbhost_len = 0;
++                      ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
++                    }
++                  if (names != namebuf)
++                    nis_freenames (names);
++                  nis_free_request (ibreq);
+                   return res;
+                 }
+               if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len)
+@@ -303,27 +305,30 @@ nis_list (const_nis_name name, unsigned 
+                     ibreq->ibr_srch.ibr_srch_val =
+                       NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_val;
+                   }
++              /* The following is a non-obvious optimization.  A
++                 nis_freeresult call would call xdr_free as the
++                 following code.  But it also would unnecessarily
++                 free the result structure.  We avoid this here
++                 along with the necessary tests.  */
++#if 1
++              xdr_free ((xdrproc_t) _xdr_nis_result, (char *)res);
++              memset (res, '\0', sizeof (*res));
++#else
+               nis_freeresult (res);
+               res = calloc (1, sizeof (nis_result));
+               if (res == NULL)
+-                {
+-                  if (have_tablepath)
+-                    free (tablepath);
+-                  __nisbind_destroy (&bptr);
+-                  nis_free_directory (dir);
+-                  return NULL;
+-                }
++                goto fail;
++#endif
+               first_try = 1; /* Try at first the old binding */
+               goto again;
+             }
+-          else if ((flags & FOLLOW_PATH) &&
+-                   NIS_RES_STATUS (res) == NIS_PARTIAL)
++          else if ((flags & FOLLOW_PATH)
++                   && NIS_RES_STATUS (res) == NIS_PARTIAL)
+             {
+-              if (!have_tablepath)
++              if (tablepath == NULL)
+                 {
+                   tablepath = __get_tablepath (ibreq->ibr_name, &bptr);
+                   tableptr = tablepath;
+-                  have_tablepath = 1;
+                 }
+               if (tableptr == NULL)
+                 {
+@@ -337,27 +342,37 @@ nis_list (const_nis_name name, unsigned 
+                   ibreq->ibr_name = strdup ("");
+                   if (ibreq->ibr_name == NULL)
+                     {
+-                      nis_free_request (ibreq);
+                       NIS_RES_STATUS (res) = NIS_NOMEMORY;
+-                      return res;
++                      goto fail;
+                     }
+                   ++done;
+                 }
+               else
+                 {
+                   ibreq->ibr_name = strdup (ibreq->ibr_name);
++                  /* The following is a non-obvious optimization.  A
++                     nis_freeresult call would call xdr_free as the
++                     following code.  But it also would unnecessarily
++                     free the result structure.  We avoid this here
++                     along with the necessary tests.  */
++#if 1
++                  xdr_free ((xdrproc_t) _xdr_nis_result, (char *)res);
++                  memset (res, '\0', sizeof (*res));
++                  if (ibreq->ibr_name == NULL)
++                    {
++                      NIS_RES_STATUS (res) = NIS_NOMEMORY;
++                      goto fail;
++                    }
++#else
+                   nis_freeresult (res);
+                   res = calloc (1, sizeof (nis_result));
+                   if (res == NULL || ibreq->ibr_name == NULL)
+                     {
+                       free (res);
+-                      nis_free_request (ibreq);
+-                      if (have_tablepath)
+-                        free (tablepath);
+-                      __nisbind_destroy (&bptr);
+-                      nis_free_directory (dir);
+-                      return NULL;
++                      res = NULL;
++                      goto fail;
+                     }
++#endif
+                   first_try = 1;
+                   goto again;
+                 }
+@@ -375,11 +390,10 @@ nis_list (const_nis_name name, unsigned 
+                 ++done;
+               else
+                 {
+-                  if (!have_tablepath)
++                  if (tablepath == NULL)
+                     {
+                       tablepath = __get_tablepath (ibreq->ibr_name, &bptr);
+                       tableptr = tablepath;
+-                      have_tablepath = 1;
+                     }
+                   if (tableptr == NULL)
+                     {
+@@ -397,9 +411,8 @@ nis_list (const_nis_name name, unsigned 
+                     ibreq->ibr_name = strdup (ibreq->ibr_name);
+                   if (ibreq->ibr_name == NULL)
+                     {
+-                      nis_free_request (ibreq);
+                       NIS_RES_STATUS (res) = NIS_NOMEMORY;
+-                      return res;
++                      goto fail;
+                     }
+                 }
+             }
+@@ -448,9 +461,8 @@ nis_list (const_nis_name name, unsigned 
+               ibreq->ibr_name = strdup (names[name_nr]);
+               if (ibreq->ibr_name == NULL)
+                 {
+-                  nis_free_request (ibreq);
+                   NIS_RES_STATUS (res) = NIS_NOMEMORY;
+-                  return res;
++                  goto fail;
+                 }
+               first_try = 1; /* Try old binding at first */
+               goto again;
+@@ -464,12 +476,15 @@ nis_list (const_nis_name name, unsigned 
+         __nis_destroy_callback (cb);
+         ibreq->ibr_cbhost.ibr_cbhost_len = 0;
+         ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
++        cb = NULL;
+       }
+       __nisbind_destroy (&bptr);
+       nis_free_directory (dir);
+     }
++  free (tablepath);
++
+   if (names != namebuf)
+     nis_freenames (names);
+--- libc/nis/ypclnt.c  25 Nov 2005 16:04:44 -0000      1.52
++++ libc/nis/ypclnt.c  8 Dec 2005 15:39:16 -0000       1.55
+@@ -46,12 +46,12 @@ struct dom_binding
+   };
+ typedef struct dom_binding dom_binding;
+-static struct timeval RPCTIMEOUT = {25, 0};
+-static struct timeval UDPTIMEOUT = {5, 0};
++static const struct timeval RPCTIMEOUT = {25, 0};
++static const struct timeval UDPTIMEOUT = {5, 0};
+ static int const MAXTRIES = 2;
+-static char __ypdomainname[NIS_MAXNAMELEN + 1] = "\0";
++static char ypdomainname[NIS_MAXNAMELEN + 1];
+ __libc_lock_define_initialized (static, ypbindlist_lock)
+-static dom_binding *__ypbindlist = NULL;
++static dom_binding *ypbindlist = NULL;
+ static void
+@@ -111,8 +111,8 @@ yp_bind_ypbindprog (const char *domain, 
+   int clnt_sock;
+   CLIENT *client;
+-  memset (&clnt_saddr, '\0', sizeof clnt_saddr);
+   clnt_saddr.sin_family = AF_INET;
++  clnt_saddr.sin_port = 0;
+   clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+   clnt_sock = RPC_ANYSOCK;
+   client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
+@@ -142,7 +142,7 @@ yp_bind_ypbindprog (const char *domain, 
+   if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
+     {
+-      fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
++      fprintf (stderr, "YPBINDPROC_DOMAIN: %s\n",
+              ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
+       return YPERR_DOMAIN;
+     }
+@@ -225,7 +225,7 @@ yp_bind (const char *indomain)
+   __libc_lock_lock (ypbindlist_lock);
+-  status = __yp_bind (indomain, &__ypbindlist);
++  status = __yp_bind (indomain, &ypbindlist);
+   __libc_lock_unlock (ypbindlist_lock);
+@@ -239,7 +239,7 @@ yp_unbind_locked (const char *indomain)
+   dom_binding *ydbptr, *ydbptr2;
+   ydbptr2 = NULL;
+-  ydbptr = __ypbindlist;
++  ydbptr = ypbindlist;
+   while (ydbptr != NULL)
+     {
+@@ -249,7 +249,7 @@ yp_unbind_locked (const char *indomain)
+         work = ydbptr;
+         if (ydbptr2 == NULL)
+-          __ypbindlist = __ypbindlist->dom_pnext;
++          ypbindlist = ypbindlist->dom_pnext;
+         else
+           ydbptr2 = ydbptr->dom_pnext;
+         __yp_unbind (work);
+@@ -306,7 +306,7 @@ do_ypcall (const char *domain, u_long pr
+   status = YPERR_YPERR;
+   __libc_lock_lock (ypbindlist_lock);
+-  ydb = __ypbindlist;
++  ydb = ypbindlist;
+   while (ydb != NULL)
+     {
+       if (strcmp (domain, ydb->dom_domain) == 0)
+@@ -365,6 +365,21 @@ do_ypcall (const char *domain, u_long pr
+   return status;
+ }
++/* Like do_ypcall, but translate the status value if necessary.  */
++static int
++do_ypcall_tr (const char *domain, u_long prog, xdrproc_t xargs,
++            caddr_t req, xdrproc_t xres, caddr_t resp)
++{
++  int status = do_ypcall (domain, prog, xargs, req, xres, resp);
++  if (status == YPERR_SUCCESS)
++    /* We cast to ypresp_val although the pointer could also be of
++       type ypresp_key_val or ypresp_master or ypresp_order or
++       ypresp_maplist.  But the stat element is in a common prefix so
++       this does not matter.  */
++    status = ypprot_err (((struct ypresp_val *) resp)->stat);
++  return status;
++}
++
+ __libc_lock_define_initialized (static, domainname_lock)
+@@ -376,21 +391,21 @@ yp_get_default_domain (char **outdomain)
+   __libc_lock_lock (domainname_lock);
+-  if (__ypdomainname[0] == '\0')
++  if (ypdomainname[0] == '\0')
+     {
+-      if (getdomainname (__ypdomainname, NIS_MAXNAMELEN))
++      if (getdomainname (ypdomainname, NIS_MAXNAMELEN))
+       result = YPERR_NODOM;
+-      else if (strcmp (__ypdomainname, "(none)") == 0)
++      else if (strcmp (ypdomainname, "(none)") == 0)
+       {
+         /* If domainname is not set, some systems will return "(none)" */
+-        __ypdomainname[0] = '\0';
++        ypdomainname[0] = '\0';
+         result = YPERR_NODOM;
+       }
+       else
+-      *outdomain = __ypdomainname;
++      *outdomain = ypdomainname;
+     }
+   else
+-    *outdomain = __ypdomainname;
++    *outdomain = ypdomainname;
+   __libc_lock_unlock (domainname_lock);
+@@ -403,14 +418,14 @@ __yp_check (char **domain)
+ {
+   char *unused;
+-  if (__ypdomainname[0] == '\0')
++  if (ypdomainname[0] == '\0')
+     if (yp_get_default_domain (&unused))
+       return 0;
+   if (domain)
+-    *domain = __ypdomainname;
++    *domain = ypdomainname;
+-  if (yp_bind (__ypdomainname) == 0)
++  if (yp_bind (ypdomainname) == 0)
+     return 1;
+   return 0;
+ }
+@@ -437,25 +452,26 @@ yp_match (const char *indomain, const ch
+   *outvallen = 0;
+   memset (&resp, '\0', sizeof (resp));
+-  result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
+-                    (caddr_t) & req, (xdrproc_t) xdr_ypresp_val,
+-                    (caddr_t) & resp);
++  result = do_ypcall_tr (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
++                       (caddr_t) &req, (xdrproc_t) xdr_ypresp_val,
++                       (caddr_t) &resp);
+   if (result != YPERR_SUCCESS)
+     return result;
+-  if (resp.stat != YP_TRUE)
+-    return ypprot_err (resp.stat);
+   *outvallen = resp.val.valdat_len;
+   *outval = malloc (*outvallen + 1);
+-  if (__builtin_expect (*outval == NULL, 0))
+-    return YPERR_RESRC;
+-  memcpy (*outval, resp.val.valdat_val, *outvallen);
+-  (*outval)[*outvallen] = '\0';
++  int status = YPERR_RESRC;
++  if (__builtin_expect (*outval != NULL, 1))
++    {
++      memcpy (*outval, resp.val.valdat_val, *outvallen);
++      (*outval)[*outvallen] = '\0';
++      status = YPERR_SUCCESS;
++    }
+   xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
+-  return YPERR_SUCCESS;
++  return status;
+ }
+ int
+@@ -478,30 +494,38 @@ yp_first (const char *indomain, const ch
+   memset (&resp, '\0', sizeof (resp));
+   result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
+-                    (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
+-                    (caddr_t) & resp);
++                    (caddr_t) &req, (xdrproc_t) xdr_ypresp_key_val,
++                    (caddr_t) &resp);
+   if (result != RPC_SUCCESS)
+     return YPERR_RPC;
+   if (resp.stat != YP_TRUE)
+     return ypprot_err (resp.stat);
+-  *outkeylen = resp.key.keydat_len;
+-  *outkey = malloc (*outkeylen + 1);
+-  if (__builtin_expect (*outkey == NULL, 0))
+-    return YPERR_RESRC;
+-  memcpy (*outkey, resp.key.keydat_val, *outkeylen);
+-  (*outkey)[*outkeylen] = '\0';
+-  *outvallen = resp.val.valdat_len;
+-  *outval = malloc (*outvallen + 1);
+-  if (__builtin_expect (*outval == NULL, 0))
+-    return YPERR_RESRC;
+-  memcpy (*outval, resp.val.valdat_val, *outvallen);
+-  (*outval)[*outvallen] = '\0';
++  int status;
++  if (__builtin_expect ((*outkey  = malloc (resp.key.keydat_len + 1)) != NULL
++                      && (*outval = malloc (resp.val.valdat_len
++                                            + 1)) != NULL, 1))
++    {
++      *outkeylen = resp.key.keydat_len;
++      memcpy (*outkey, resp.key.keydat_val, *outkeylen);
++      (*outkey)[*outkeylen] = '\0';
++
++      *outvallen = resp.val.valdat_len;
++      memcpy (*outval, resp.val.valdat_val, *outvallen);
++      (*outval)[*outvallen] = '\0';
++
++      status = YPERR_SUCCESS;
++    }
++  else
++    {
++      free (*outkey);
++      status = YPERR_RESRC;
++    }
+   xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
+-  return YPERR_SUCCESS;
++  return status;
+ }
+ int
+@@ -527,31 +551,37 @@ yp_next (const char *indomain, const cha
+   *outkeylen = *outvallen = 0;
+   memset (&resp, '\0', sizeof (resp));
+-  result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
+-                    (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
+-                    (caddr_t) & resp);
++  result = do_ypcall_tr (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
++                       (caddr_t) &req, (xdrproc_t) xdr_ypresp_key_val,
++                       (caddr_t) &resp);
+   if (result != YPERR_SUCCESS)
+     return result;
+-  if (resp.stat != YP_TRUE)
+-    return ypprot_err (resp.stat);
+-  *outkeylen = resp.key.keydat_len;
+-  *outkey = malloc (*outkeylen + 1);
+-  if (__builtin_expect (*outkey == NULL, 0))
+-    return YPERR_RESRC;
+-  memcpy (*outkey, resp.key.keydat_val, *outkeylen);
+-  (*outkey)[*outkeylen] = '\0';
+-  *outvallen = resp.val.valdat_len;
+-  *outval = malloc (*outvallen + 1);
+-  if (__builtin_expect (*outval == NULL, 0))
+-    return YPERR_RESRC;
+-  memcpy (*outval, resp.val.valdat_val, *outvallen);
+-  (*outval)[*outvallen] = '\0';
++  int status;
++  if (__builtin_expect ((*outkey  = malloc (resp.key.keydat_len + 1)) != NULL
++                      && (*outval = malloc (resp.val.valdat_len
++                                            + 1)) != NULL, 1))
++    {
++      *outkeylen = resp.key.keydat_len;
++      memcpy (*outkey, resp.key.keydat_val, *outkeylen);
++      (*outkey)[*outkeylen] = '\0';
++
++      *outvallen = resp.val.valdat_len;
++      memcpy (*outval, resp.val.valdat_val, *outvallen);
++      (*outval)[*outvallen] = '\0';
++
++      status = YPERR_SUCCESS;
++    }
++  else
++    {
++      free (*outkey);
++      status = YPERR_RESRC;
++    }
+   xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
+-  return YPERR_SUCCESS;
++  return status;
+ }
+ int
+@@ -570,13 +600,12 @@ yp_master (const char *indomain, const c
+   memset (&resp, '\0', sizeof (ypresp_master));
+-  result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
+-        (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
++  result = do_ypcall_tr (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
++                       (caddr_t) &req, (xdrproc_t) xdr_ypresp_master,
++                       (caddr_t) &resp);
+   if (result != YPERR_SUCCESS)
+     return result;
+-  if (resp.stat != YP_TRUE)
+-    return ypprot_err (resp.stat);
+   *outname = strdup (resp.peer);
+   xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
+@@ -601,18 +630,17 @@ yp_order (const char *indomain, const ch
+   memset (&resp, '\0', sizeof (resp));
+-  result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
+-         (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
++  result = do_ypcall_tr (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
++                       (caddr_t) &req, (xdrproc_t) xdr_ypresp_order,
++                       (caddr_t) &resp);
+-  if (result != YPERR_SUCCESS)
++  if (result == YPERR_SUCCESS)
+     return result;
+-  if (resp.stat != YP_TRUE)
+-    return ypprot_err (resp.stat);
+   *outorder = resp.ordernum;
+   xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
+-  return YPERR_SUCCESS;
++  return result;
+ }
+ struct ypresp_all_data
+@@ -694,8 +722,8 @@ yp_all (const char *indomain, const char
+   int clnt_sock;
+   int saved_errno = errno;
+-  if (indomain == NULL || indomain[0] == '\0' ||
+-      inmap == NULL || inmap == '\0')
++  if (indomain == NULL || indomain[0] == '\0'
++      || inmap == NULL || inmap[0] == '\0')
+     return YPERR_BADARGS;
+   try = 0;
+@@ -733,9 +761,9 @@ yp_all (const char *indomain, const char
+                         (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
+                         (caddr_t) &data, RPCTIMEOUT);
+-      if (result != RPC_SUCCESS)
++      if (__builtin_expect (result != RPC_SUCCESS, 0))
+       {
+-        /* Print the error message only on the last try */
++        /* Print the error message only on the last try.  */
+         if (try == MAXTRIES - 1)
+           clnt_perror (clnt, "yp_all: clnt_call");
+         res = YPERR_RPC;
+@@ -759,6 +787,7 @@ yp_all (const char *indomain, const char
+ }
+ int
++
+ yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
+ {
+   struct ypresp_maplist resp;
+@@ -769,62 +798,82 @@ yp_maplist (const char *indomain, struct
+   memset (&resp, '\0', sizeof (resp));
+-  result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
+-    (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
+-
+-  if (result != YPERR_SUCCESS)
+-    return result;
+-  if (resp.stat != YP_TRUE)
+-    return ypprot_err (resp.stat);
+-
+-  *outmaplist = resp.maps;
+-  /* We give the list not free, this will be done by ypserv
+-     xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
++  result = do_ypcall_tr (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
++                       (caddr_t) &indomain, (xdrproc_t) xdr_ypresp_maplist,
++                       (caddr_t) &resp);
++
++  if (__builtin_expect (result == YPERR_SUCCESS, 1))
++    {
++      *outmaplist = resp.maps;
++      /* We don't free the list, this will be done by ypserv
++       xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
++    }
+-  return YPERR_SUCCESS;
++  return result;
+ }
+ const char *
+ yperr_string (const int error)
+ {
++  const char *str;
+   switch (error)
+     {
+     case YPERR_SUCCESS:
+-      return _("Success");
++      str = N_("Success");
++      break;
+     case YPERR_BADARGS:
+-      return _("Request arguments bad");
++      str = N_("Request arguments bad");
++      break;
+     case YPERR_RPC:
+-      return _("RPC failure on NIS operation");
++      str = N_("RPC failure on NIS operation");
++      break;
+     case YPERR_DOMAIN:
+-      return _("Can't bind to server which serves this domain");
++      str = N_("Can't bind to server which serves this domain");
++      break;
+     case YPERR_MAP:
+-      return _("No such map in server's domain");
++      str = N_("No such map in server's domain");
++      break;
+     case YPERR_KEY:
+-      return _("No such key in map");
++      str = N_("No such key in map");
++      break;
+     case YPERR_YPERR:
+-      return _("Internal NIS error");
++      str = N_("Internal NIS error");
++      break;
+     case YPERR_RESRC:
+-      return _("Local resource allocation failure");
++      str = N_("Local resource allocation failure");
++      break;
+     case YPERR_NOMORE:
+-      return _("No more records in map database");
++      str = N_("No more records in map database");
++      break;
+     case YPERR_PMAP:
+-      return _("Can't communicate with portmapper");
++      str = N_("Can't communicate with portmapper");
++      break;
+     case YPERR_YPBIND:
+-      return _("Can't communicate with ypbind");
++      str = N_("Can't communicate with ypbind");
++      break;
+     case YPERR_YPSERV:
+-      return _("Can't communicate with ypserv");
++      str = N_("Can't communicate with ypserv");
++      break;
+     case YPERR_NODOM:
+-      return _("Local domain name not set");
++      str = N_("Local domain name not set");
++      break;
+     case YPERR_BADDB:
+-      return _("NIS map database is bad");
++      str = N_("NIS map database is bad");
++      break;
+     case YPERR_VERS:
+-      return _("NIS client/server version mismatch - can't supply service");
++      str = N_("NIS client/server version mismatch - can't supply service");
++      break;
+     case YPERR_ACCESS:
+-      return _("Permission denied");
++      str = N_("Permission denied");
++      break;
+     case YPERR_BUSY:
+-      return _("Database is busy");
++      str = N_("Database is busy");
++      break;
++    default:
++      str = N_("Unknown NIS error code");
++      break;
+     }
+-  return _("Unknown NIS error code");
++  return _(str);
+ }
+ static const int8_t yp_2_yperr[] =
+@@ -854,19 +903,26 @@ libnsl_hidden_def (ypprot_err)
+ const char *
+ ypbinderr_string (const int error)
+ {
++  const char *str;
+   switch (error)
+     {
+     case 0:
+-      return _("Success");
++      str = N_("Success");
++      break;
+     case YPBIND_ERR_ERR:
+-      return _("Internal ypbind error");
++      str = N_("Internal ypbind error");
++      break;
+     case YPBIND_ERR_NOSERV:
+-      return _("Domain not bound");
++      str = N_("Domain not bound");
++      break;
+     case YPBIND_ERR_RESC:
+-      return _("System resource allocation failure");
++      str = N_("System resource allocation failure");
++      break;
+     default:
+-      return _("Unknown ypbind error");
++      str = N_("Unknown ypbind error");
++      break;
+     }
++  return _(str);
+ }
+ libnsl_hidden_def (ypbinderr_string)
+@@ -948,6 +1004,7 @@ again:
+     {
+       if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
+       {
++        auth_destroy (clnt->cl_auth);
+         clnt->cl_auth = authunix_create_default ();
+         goto again;
+       }
+--- libc/nis/nss_nisplus/nisplus-alias.c       25 Sep 2003 19:44:20 -0000      1.16
++++ libc/nis/nss_nisplus/nisplus-alias.c       3 Dec 2005 17:01:45 -0000       1.17
+@@ -17,6 +17,7 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
++#include <atomic.h>
+ #include <nss.h>
+ #include <errno.h>
+ #include <ctype.h>
+@@ -32,7 +33,7 @@ __libc_lock_define_initialized (static, 
+ static nis_result *result;
+ static u_long next_entry;
+ static nis_name tablename_val;
+-static u_long tablename_len;
++static size_t tablename_len;
+ #define NISENTRYVAL(idx,col,res) \
+         ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
+@@ -45,19 +46,26 @@ _nss_create_tablename (int *errnop)
+ {
+   if (tablename_val == NULL)
+     {
+-      char buf [40 + strlen (nis_local_directory ())];
+-      char *p;
++      const char *local_dir = nis_local_directory ();
++      size_t local_dir_len = strlen (local_dir);
++      static const char prefix[] = "mail_aliases.org_dir.";
+-      p = __stpcpy (buf, "mail_aliases.org_dir.");
+-      p = __stpcpy (p, nis_local_directory ());
+-      tablename_val = __strdup (buf);
+-      if (tablename_val == NULL)
++      char *p = malloc (sizeof (prefix) + local_dir_len);
++      if (p == NULL)
+       {
+         *errnop = errno;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      tablename_len = strlen (tablename_val);
++
++      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
++
++      tablename_len = sizeof (prefix) - 1 + local_dir_len;
++
++      atomic_write_barrier ();
++
++      tablename_val = p;
+     }
++
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -75,81 +83,73 @@ _nss_nisplus_parse_aliasent (nis_result 
+                "mail_aliases") != 0
+       || result->objects.objects_val[entry].EN_data.en_cols.en_cols_len < 2)
+     return 0;
+-  else
++
++  char *first_unused = buffer + NISENTRYLEN (0, 1, result) + 1;
++  size_t room_left = (buflen - (buflen % __alignof__ (char *))
++                    - NISENTRYLEN (0, 1, result) - 2);
++
++  if (NISENTRYLEN (entry, 1, result) >= buflen)
+     {
+-      char *first_unused = buffer + NISENTRYLEN (0, 1, result) + 1;
+-      size_t room_left =
+-      buflen - (buflen % __alignof__ (char *)) -
+-      NISENTRYLEN (0, 1, result) - 2;
+-      char *line;
+-      char *cp;
++      /* The line is too long for our buffer.  */
++    no_more_room:
++      *errnop = ERANGE;
++      return -1;
++    }
+-      if (NISENTRYLEN (entry, 1, result) >= buflen)
+-      {
+-        /* The line is too long for our buffer.  */
+-      no_more_room:
+-        *errnop = ERANGE;
+-        return -1;
+-      }
+-      else
+-      {
+-        cp = __stpncpy (buffer, NISENTRYVAL (entry, 1, result),
+-                       NISENTRYLEN (entry, 1, result));
+-        *cp = '\0';
+-      }
++  char *cp = __stpncpy (buffer, NISENTRYVAL (entry, 1, result),
++                      NISENTRYLEN (entry, 1, result));
++  *cp = '\0';
++
++  if (NISENTRYLEN(entry, 0, result) >= room_left)
++    goto no_more_room;
++
++  alias->alias_local = 0;
++  alias->alias_members_len = 0;
++  *first_unused = '\0';
++  ++first_unused;
++  cp = __stpncpy (first_unused, NISENTRYVAL (entry, 0, result),
++                NISENTRYLEN (entry, 0, result));
++  *cp = '\0';
++  alias->alias_name = first_unused;
++
++  /* Terminate the line for any case.  */
++  cp = strpbrk (alias->alias_name, "#\n");
++  if (cp != NULL)
++    *cp = '\0';
++
++  first_unused += strlen (alias->alias_name) +1;
++  /* Adjust the pointer so it is aligned for
++     storing pointers.  */
++  first_unused += __alignof__ (char *) - 1;
++  first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *));
++  alias->alias_members = (char **) first_unused;
+-      if (NISENTRYLEN(entry, 0, result) >= room_left)
+-      goto no_more_room;
++  char *line = buffer;
++  while (*line != '\0')
++    {
++      /* Skip leading blanks.  */
++      while (isspace (*line))
++      ++line;
++
++      if (*line == '\0')
++      break;
+-      alias->alias_local = 0;
+-      alias->alias_members_len = 0;
+-      *first_unused = '\0';
+-      ++first_unused;
+-      cp = __stpncpy (first_unused, NISENTRYVAL (entry, 0, result),
+-                    NISENTRYLEN (entry, 0, result));
+-      *cp = '\0';
+-      alias->alias_name = first_unused;
+-
+-      /* Terminate the line for any case.  */
+-      cp = strpbrk (alias->alias_name, "#\n");
+-      if (cp != NULL)
+-      *cp = '\0';
+-
+-      first_unused += strlen (alias->alias_name) +1;
+-      /* Adjust the pointer so it is aligned for
+-       storing pointers.  */
+-      first_unused += __alignof__ (char *) - 1;
+-      first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *));
+-      alias->alias_members = (char **) first_unused;
++      if (room_left < sizeof (char *))
++      goto no_more_room;
++      room_left -= sizeof (char *);
++      alias->alias_members[alias->alias_members_len] = line;
+-      line = buffer;
++      while (*line != '\0' && *line != ',')
++      ++line;
+-      while (*line != '\0')
++      if (line != alias->alias_members[alias->alias_members_len])
+       {
+-        /* Skip leading blanks.  */
+-        while (isspace (*line))
+-          ++line;
+-
+-        if (*line == '\0')
+-          break;
+-
+-        if (room_left < sizeof (char *))
+-          goto no_more_room;
+-        room_left -= sizeof (char *);
+-        alias->alias_members[alias->alias_members_len] = line;
+-
+-        while (*line != '\0' && *line != ',')
+-          ++line;
+-
+-        if (line != alias->alias_members[alias->alias_members_len])
+-          {
+-            *line++ = '\0';
+-            alias->alias_members_len++;
+-          }
++        *line++ = '\0';
++        alias->alias_members_len++;
+       }
+-
+-      return alias->alias_members_len == 0 ? 0 : 1;
+     }
++
++  return alias->alias_members_len == 0 ? 0 : 1;
+ }
+ static enum nss_status
+@@ -158,9 +158,11 @@ internal_setaliasent (void)
+   enum nss_status status;
+   int err;
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result !=  NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   if (_nss_create_tablename (&err) != NSS_STATUS_SUCCESS)
+     return NSS_STATUS_UNAVAIL;
+@@ -203,9 +205,11 @@ _nss_nisplus_endaliasent (void)
+ {
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   next_entry = 0;
+   __libc_lock_unlock (lock);
+@@ -240,7 +244,8 @@ internal_nisplus_getaliasent_r (struct a
+       return NSS_STATUS_TRYAGAIN;
+       ++next_entry;
+-    } while (!parse_res);
++    }
++  while (!parse_res);
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -268,7 +273,12 @@ _nss_nisplus_getaliasbyname_r (const cha
+   if (tablename_val == NULL)
+     {
++      __libc_lock_lock (lock);
++
+       enum nss_status status = _nss_create_tablename (errnop);
++
++      __libc_lock_unlock (lock);
++
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+     }
+@@ -278,35 +288,34 @@ _nss_nisplus_getaliasbyname_r (const cha
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+     }
+-  else
+-    {
+-      nis_result *result;
+-      char buf[strlen (name) + 30 + tablename_len];
+-      int olderr = errno;
+-      sprintf (buf, "[name=%s],%s", name, tablename_val);
++  char buf[strlen (name) + 9 + tablename_len];
++  int olderr = errno;
+-      result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++  snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
+-      if (result == NULL)
+-      {
+-        *errnop = ENOMEM;
+-        return NSS_STATUS_TRYAGAIN;
+-      }
+-      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+-      return niserr2nss (result->status);
++  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+-      parse_res = _nss_nisplus_parse_aliasent (result, 0, alias,
+-                                             buffer, buflen, errnop);
+-      if (parse_res < 1)
+-      {
+-        __set_errno (olderr);
++  if (result == NULL)
++    {
++      *errnop = ENOMEM;
++      return NSS_STATUS_TRYAGAIN;
++    }
+-        if (parse_res == -1)
+-          return NSS_STATUS_TRYAGAIN;
+-        else
+-          return NSS_STATUS_NOTFOUND;
+-      }
+-      return NSS_STATUS_SUCCESS;
++  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
++    return niserr2nss (result->status);
++
++  parse_res = _nss_nisplus_parse_aliasent (result, 0, alias,
++                                         buffer, buflen, errnop);
++  if (__builtin_expect (parse_res < 1, 0))
++    {
++      __set_errno (olderr);
++
++      if (parse_res == -1)
++      return NSS_STATUS_TRYAGAIN;
++      else
++      return NSS_STATUS_NOTFOUND;
+     }
++
++  return NSS_STATUS_SUCCESS;
+ }
+--- libc/nis/nss_nisplus/nisplus-ethers.c      25 Sep 2003 19:44:20 -0000      1.19
++++ libc/nis/nss_nisplus/nisplus-ethers.c      3 Dec 2005 21:45:55 -0000       1.21
+@@ -17,15 +17,17 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+-#include <nss.h>
+-#include <errno.h>
++#include <atomic.h>
+ #include <ctype.h>
+-#include <string.h>
+-#include <bits/libc-lock.h>
++#include <errno.h>
++#include <inttypes.h>
+ #include <netdb.h>
++#include <nss.h>
++#include <string.h>
+ #include <netinet/ether.h>
+-#include <rpcsvc/nis.h>
+ #include <netinet/if_ether.h>
++#include <rpcsvc/nis.h>
++#include <bits/libc-lock.h>
+ #include "nss-nisplus.h"
+@@ -70,7 +72,14 @@ _nss_nisplus_parse_etherent (nis_result 
+   room_left -= (NISENTRYLEN (0, 0, result) +1);
+   ether->e_name = p;
+-  ether->e_addr = *ether_aton (NISENTRYVAL (0, 1, result));
++  struct ether_addr *ea = ether_aton (NISENTRYVAL (0, 1, result));
++  if (ea == NULL)
++    {
++      *errnop = EINVAL;
++      return -2;
++    }
++
++  ether->e_addr = *ea;
+   return 1;
+ }
+@@ -80,18 +89,24 @@ _nss_create_tablename (int *errnop)
+ {
+   if (tablename_val == NULL)
+     {
+-      char buf [40 + strlen (nis_local_directory ())];
+-      char *p;
++      const char *local_dir = nis_local_directory ();
++      size_t local_dir_len = strlen (local_dir);
++      static const char prefix[] = "ethers.org_dir.";
+-      p = __stpcpy (buf, "ethers.org_dir.");
+-      p = __stpcpy (p, nis_local_directory ());
+-      tablename_val = __strdup (buf);
+-      if (tablename_val == NULL)
++      char *p = malloc (sizeof (prefix) + local_dir_len);
++      if (p == NULL)
+       {
+         *errnop = errno;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      tablename_len = strlen (tablename_val);
++
++      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
++
++      tablename_len = sizeof (prefix) - 1 + local_dir_len;
++
++      atomic_write_barrier ();
++
++      tablename_val = p;
+     }
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -107,9 +122,11 @@ _nss_nisplus_setetherent (int stayopen)
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   if (_nss_create_tablename (&err) != NSS_STATUS_SUCCESS)
+     status = NSS_STATUS_UNAVAIL;
+@@ -124,9 +141,11 @@ _nss_nisplus_endetherent (void)
+ {
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   __libc_lock_unlock (lock);
+@@ -137,8 +156,6 @@ static enum nss_status
+ internal_nisplus_getetherent_r (struct etherent *ether, char *buffer,
+                               size_t buflen, int *errnop)
+ {
+-  int parse_res;
+-
+   if (tablename_val == NULL)
+     {
+       enum nss_status status = _nss_create_tablename (errnop);
+@@ -148,6 +165,7 @@ internal_nisplus_getetherent_r (struct e
+     }
+   /* Get the next entry until we found a correct one. */
++  int parse_res;
+   do
+     {
+       nis_result *saved_result;
+@@ -161,11 +179,8 @@ internal_nisplus_getetherent_r (struct e
+       }
+       else
+       {
+-        nis_result *res2;
+-
+-        res2 = nis_next_entry(tablename_val, &result->cookie);
+         saved_result = result;
+-        result = res2;
++        result = nis_next_entry (tablename_val, &result->cookie);
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           {
+             nis_freeresult (saved_result);
+@@ -178,17 +193,15 @@ internal_nisplus_getetherent_r (struct e
+       if (parse_res == -1)
+       {
+         nis_freeresult (result);
+-        *errnop = ERANGE;
+         result = saved_result;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      else
+-      {
+-        if (saved_result != NULL)
+-          nis_freeresult (saved_result);
+-      }
+-    } while (!parse_res);
++      if (saved_result != NULL)
++      nis_freeresult (saved_result);
++
++    }
++  while (!parse_res);
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -212,8 +225,6 @@ enum nss_status
+ _nss_nisplus_gethostton_r (const char *name, struct etherent *eth,
+                          char *buffer, size_t buflen, int *errnop)
+ {
+-  int parse_res;
+-
+   if (tablename_val == NULL)
+     {
+       enum nss_status status = _nss_create_tablename (errnop);
+@@ -227,56 +238,57 @@ _nss_nisplus_gethostton_r (const char *n
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+     }
+-  else
+-    {
+-      nis_result *result;
+-      char buf[strlen (name) + 40 + tablename_len];
+-      int olderr = errno;
+-      sprintf (buf, "[name=%s],%s", name, tablename_val);
++  char buf[strlen (name) + 9 + tablename_len];
++  int olderr = errno;
+-      result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++  snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
+-      if (result == NULL)
+-      {
+-        *errnop = ENOMEM;
+-        return NSS_STATUS_TRYAGAIN;
+-      }
+-      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+-      {
+-        enum nss_status status = niserr2nss (result->status);
+-        nis_freeresult (result);
+-        return status;
+-      }
++  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++
++  if (result == NULL)
++    {
++      *errnop = ENOMEM;
++      return NSS_STATUS_TRYAGAIN;
++    }
++
++  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
++    {
++      enum nss_status status = niserr2nss (result->status);
++      nis_freeresult (result);
++      return status;
++    }
+-      parse_res = _nss_nisplus_parse_etherent (result, eth, buffer,
++  int parse_res = _nss_nisplus_parse_etherent (result, eth, buffer,
+                                              buflen, errnop);
+-      if (parse_res < 1)
+-      {
+-        __set_errno (olderr);
++  if (__builtin_expect (parse_res < 1, 0))
++    {
++      __set_errno (olderr);
+-        if (parse_res == -1)
+-          {
+-            nis_freeresult (result);
+-            *errnop = ERANGE;
+-            return NSS_STATUS_TRYAGAIN;
+-          }
+-        else
+-         return NSS_STATUS_NOTFOUND;
++      if (parse_res == -1)
++      {
++        nis_freeresult (result);
++        return NSS_STATUS_TRYAGAIN;
+       }
+-      return NSS_STATUS_SUCCESS;
++      else
++      return NSS_STATUS_NOTFOUND;
+     }
++
++  return NSS_STATUS_SUCCESS;
+ }
+ enum nss_status
+-_nss_nisplus_getntohost_r (const struct ether_addr *addr,
+-                         struct etherent *eth,
++_nss_nisplus_getntohost_r (const struct ether_addr *addr, struct etherent *eth,
+                          char *buffer, size_t buflen, int *errnop)
+ {
+   if (tablename_val == NULL)
+     {
++      __libc_lock_lock (lock);
++
+       enum nss_status status = _nss_create_tablename (errnop);
++      __libc_lock_unlock (lock);
++
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+     }
+@@ -286,44 +298,44 @@ _nss_nisplus_getntohost_r (const struct 
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+     }
+-  else
++
++  char buf[26 + tablename_len];
++
++  snprintf (buf, sizeof (buf),
++          "[addr=%" PRIx8 ":%" PRIx8 ":%" PRIx8 ":%" PRIx8 ":%" PRIx8
++          ":%" PRIx8 "],%s",
++          addr->ether_addr_octet[0], addr->ether_addr_octet[1],
++          addr->ether_addr_octet[2], addr->ether_addr_octet[3],
++          addr->ether_addr_octet[4], addr->ether_addr_octet[5],
++          tablename_val);
++
++  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++
++  if (result == NULL)
+     {
+-      int parse_res;
+-      nis_result *result;
+-      char buf[255 + tablename_len];
+-
+-      sprintf (buf, "[addr=%x:%x:%x:%x:%x:%x],ethers.org_dir",
+-             addr->ether_addr_octet[0], addr->ether_addr_octet[1],
+-             addr->ether_addr_octet[2], addr->ether_addr_octet[3],
+-             addr->ether_addr_octet[4], addr->ether_addr_octet[5]);
++      *errnop = ENOMEM;
++      return NSS_STATUS_TRYAGAIN;
++    }
+-      result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
++    {
++      enum nss_status status = niserr2nss (result->status);
++      nis_freeresult (result);
++      return status;
++    }
+-      if (result == NULL)
+-      {
+-        *errnop = ENOMEM;
+-        return NSS_STATUS_TRYAGAIN;
+-      }
+-      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
++  int parse_res = _nss_nisplus_parse_etherent (result, eth, buffer,
++                                             buflen, errnop);
++  if (__builtin_expect (parse_res < 1, 0))
++    {
++      if (parse_res == -1)
+       {
+-        enum nss_status status = niserr2nss (result->status);
+         nis_freeresult (result);
+-        return status;
++        return NSS_STATUS_TRYAGAIN;
+       }
+-      parse_res = _nss_nisplus_parse_etherent (result, eth, buffer,
+-                                             buflen, errnop);
+-      if (parse_res < 1)
+-      {
+-        if (parse_res == -1)
+-          {
+-            nis_freeresult (result);
+-            *errnop = ERANGE;
+-            return NSS_STATUS_TRYAGAIN;
+-          }
+-        else
+-          return NSS_STATUS_NOTFOUND;
+-      }
+-      return NSS_STATUS_SUCCESS;
++      return NSS_STATUS_NOTFOUND;
+     }
++
++  return NSS_STATUS_SUCCESS;
+ }
+--- libc/nis/nss_nisplus/nisplus-grp.c 25 Sep 2003 19:44:20 -0000      1.16
++++ libc/nis/nss_nisplus/nisplus-grp.c 3 Dec 2005 05:04:16 -0000       1.18
+@@ -17,6 +17,7 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
++#include <atomic.h>
+ #include <nss.h>
+ #include <grp.h>
+ #include <ctype.h>
+@@ -28,31 +29,39 @@
+ #include "nss-nisplus.h"
+ #include "nisplus-parser.h"
++
+ __libc_lock_define_initialized (static, lock);
+ static nis_result *result;
+ static unsigned long next_entry;
+ static nis_name tablename_val;
+-static u_long tablename_len;
++static size_t tablename_len;
+ static enum nss_status
+ _nss_create_tablename (int *errnop)
+ {
+   if (tablename_val == NULL)
+     {
+-      char buf [40 + strlen (nis_local_directory ())];
+-      char *p;
++      const char *local_dir = nis_local_directory ();
++      size_t local_dir_len = strlen (local_dir);
++      static const char prefix[] = "group.org_dir.";
+-      p = __stpcpy (buf, "group.org_dir.");
+-      p = __stpcpy (p, nis_local_directory ());
+-      tablename_val = __strdup (buf);
+-      if (tablename_val == NULL)
++      char *p = malloc (sizeof (prefix) + local_dir_len);
++      if (p == NULL)
+       {
+         *errnop = errno;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      tablename_len = strlen (tablename_val);
++
++      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
++
++      tablename_len = sizeof (prefix) - 1 + local_dir_len;
++
++      atomic_write_barrier ();
++
++      tablename_val = p;
+     }
++
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -60,16 +69,20 @@ static enum nss_status
+ internal_setgrent (void)
+ {
+   enum nss_status status;
+-  int err;
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   next_entry = 0;
+   if (tablename_val == NULL)
+-    if (_nss_create_tablename (&err) != NSS_STATUS_SUCCESS)
+-      return NSS_STATUS_UNAVAIL;
++    {
++      int err;
++      if (_nss_create_tablename (&err) != NSS_STATUS_SUCCESS)
++      return NSS_STATUS_UNAVAIL;
++    }
+   result = nis_list (tablename_val, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
+   if (result == NULL)
+@@ -108,9 +121,11 @@ _nss_nisplus_endgrent (void)
+ {
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   __libc_lock_unlock (lock);
+@@ -173,8 +188,12 @@ _nss_nisplus_getgrnam_r (const char *nam
+   if (tablename_val == NULL)
+     {
++      __libc_lock_lock (lock);
++
+       enum nss_status status = _nss_create_tablename (errnop);
++      __libc_lock_unlock (lock);
++
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+     }
+@@ -184,47 +203,46 @@ _nss_nisplus_getgrnam_r (const char *nam
+       *errnop = EINVAL;
+       return NSS_STATUS_NOTFOUND;
+     }
+-  else
++
++  nis_result *result;
++  char buf[strlen (name) + 9 + tablename_len];
++  int olderr = errno;
++
++  snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
++
++  result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
++
++  if (result == NULL)
+     {
+-      nis_result *result;
+-      char buf[strlen (name) + 24 + tablename_len];
+-      int olderr = errno;
++      *errnop = ENOMEM;
++      return NSS_STATUS_TRYAGAIN;
++    }
+-      sprintf (buf, "[name=%s],%s", name, tablename_val);
++  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
++    {
++      enum nss_status status = niserr2nss (result->status);
+-      result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
++      nis_freeresult (result);
++      return status;
++    }
+-      if (result == NULL)
++  parse_res = _nss_nisplus_parse_grent (result, 0, gr, buffer, buflen, errnop);
++  nis_freeresult (result);
++  if (__builtin_expect (parse_res < 1, 0))
++    {
++      if (parse_res == -1)
+       {
+-        *errnop = ENOMEM;
++        *errnop = ERANGE;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
++      else
+       {
+-        enum nss_status status = niserr2nss (result->status);
+-
+-        nis_freeresult (result);
+-        return status;
+-      }
+-
+-      parse_res = _nss_nisplus_parse_grent (result, 0, gr, buffer, buflen,
+-                                          errnop);
+-      nis_freeresult (result);
+-      if (parse_res < 1)
+-      {
+-        if (parse_res == -1)
+-          {
+-            *errnop = ERANGE;
+-            return NSS_STATUS_TRYAGAIN;
+-          }
+-        else
+-          {
+-            __set_errno (olderr);
+-            return NSS_STATUS_NOTFOUND;
+-          }
++        __set_errno (olderr);
++        return NSS_STATUS_NOTFOUND;
+       }
+-      return NSS_STATUS_SUCCESS;
+     }
++
++  return NSS_STATUS_SUCCESS;
+ }
+ enum nss_status
+@@ -233,53 +251,57 @@ _nss_nisplus_getgrgid_r (const gid_t gid
+ {
+   if (tablename_val == NULL)
+     {
++      __libc_lock_lock (lock);
++
+       enum nss_status status = _nss_create_tablename (errnop);
++      __libc_lock_unlock (lock);
++
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+     }
+-  {
+-    int parse_res;
+-    nis_result *result;
+-    char buf[36 + tablename_len];
+-    int olderr = errno;
+-
+-    sprintf (buf, "[gid=%lu],%s", (unsigned long int) gid, tablename_val);
+-
+-    result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+-
+-    if (result == NULL)
+-      {
+-      *errnop = ENOMEM;
+-      return NSS_STATUS_TRYAGAIN;
+-      }
+-    if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+-      {
+-      enum nss_status status = niserr2nss (result->status);
++  int parse_res;
++  nis_result *result;
++  char buf[8 + 3 * sizeof (unsigned long int) + tablename_len];
++  int olderr = errno;
+-      __set_errno (olderr);
++  snprintf (buf, sizeof (buf), "[gid=%lu],%s",
++          (unsigned long int) gid, tablename_val);
+-      nis_freeresult (result);
+-      return status;
+-      }
++  result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++
++  if (result == NULL)
++    {
++      *errnop = ENOMEM;
++      return NSS_STATUS_TRYAGAIN;
++    }
+-    parse_res = _nss_nisplus_parse_grent (result, 0, gr, buffer, buflen,
+-                                        errnop);
++  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
++    {
++      enum nss_status status = niserr2nss (result->status);
+-    nis_freeresult (result);
+-    if (parse_res < 1)
+-      {
+-      __set_errno (olderr);
+-
+-      if (parse_res == -1)
+-        {
+-          *errnop = ERANGE;
+-          return NSS_STATUS_TRYAGAIN;
+-        }
+-      else
+-        return NSS_STATUS_NOTFOUND;
+-      }
+-    return NSS_STATUS_SUCCESS;
+-  }
++      __set_errno (olderr);
++
++      nis_freeresult (result);
++      return status;
++    }
++
++  parse_res = _nss_nisplus_parse_grent (result, 0, gr, buffer, buflen, errnop);
++
++  nis_freeresult (result);
++  if (__builtin_expect (parse_res < 1, 0))
++    {
++      __set_errno (olderr);
++
++      if (parse_res == -1)
++      {
++        *errnop = ERANGE;
++        return NSS_STATUS_TRYAGAIN;
++      }
++      else
++      return NSS_STATUS_NOTFOUND;
++    }
++
++  return NSS_STATUS_SUCCESS;
+ }
+--- libc/nis/nss_nisplus/nisplus-hosts.c       25 Sep 2003 19:44:20 -0000      1.27
++++ libc/nis/nss_nisplus/nisplus-hosts.c       3 Dec 2005 17:47:33 -0000       1.28
+@@ -17,15 +17,16 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+-#include <nss.h>
+-#include <netdb.h>
+-#include <errno.h>
++#include <atomic.h>
+ #include <ctype.h>
++#include <errno.h>
++#include <netdb.h>
++#include <nss.h>
+ #include <string.h>
+-#include <netinet/in.h>
+ #include <arpa/inet.h>
+-#include <bits/libc-lock.h>
++#include <netinet/in.h>
+ #include <rpcsvc/nis.h>
++#include <bits/libc-lock.h>
+ #include "nss-nisplus.h"
+@@ -180,19 +181,26 @@ _nss_create_tablename (int *errnop)
+ {
+   if (tablename_val == NULL)
+     {
+-      char buf [40 + strlen (nis_local_directory ())];
+-      char *p;
++      const char *local_dir = nis_local_directory ();
++      size_t local_dir_len = strlen (local_dir);
++      static const char prefix[] = "hosts.org_dir.";
+-      p = __stpcpy (buf, "hosts.org_dir.");
+-      p = __stpcpy (p, nis_local_directory ());
+-      tablename_val = __strdup (buf);
+-      if (tablename_val == NULL)
++      char *p = malloc (sizeof (prefix) + local_dir_len);
++      if (p == NULL)
+       {
+         *errnop = errno;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      tablename_len = strlen (tablename_val);
++
++      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
++
++      tablename_len = sizeof (prefix) - 1 + local_dir_len;
++
++      atomic_write_barrier ();
++
++      tablename_val = p;
+     }
++
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -204,9 +212,11 @@ _nss_nisplus_sethostent (int stayopen)
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   if (tablename_val == NULL)
+     status = _nss_create_tablename (&err);
+@@ -221,9 +231,11 @@ _nss_nisplus_endhostent (void)
+ {
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   __libc_lock_unlock (lock);
+@@ -335,8 +347,12 @@ internal_gethostbyname2_r (const char *n
+   if (tablename_val == NULL)
+     {
++      __libc_lock_lock (lock);
++
+       enum nss_status status = _nss_create_tablename (errnop);
++      __libc_lock_unlock (lock);
++
+       if (status != NSS_STATUS_SUCCESS)
+       {
+         *herrnop = NETDB_INTERNAL;
+@@ -350,75 +366,81 @@ internal_gethostbyname2_r (const char *n
+       *herrnop = NETDB_INTERNAL;
+       return NSS_STATUS_NOTFOUND;
+     }
+-  else
+-    {
+-      nis_result *result;
+-      char buf[strlen (name) + 255 + tablename_len];
+-      int olderr = errno;
+-
+-      /* Search at first in the alias list, and use the correct name
+-       for the next search */
+-      sprintf (buf, "[name=%s],%s", name, tablename_val);
+-      result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+-
+-      if (result != NULL)
+-      {
+-        /* If we do not find it, try it as original name. But if the
+-           database is correct, we should find it in the first case, too */
+-        if ((result->status != NIS_SUCCESS
+-             && result->status != NIS_S_SUCCESS)
+-            || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
+-            || strcmp (result->objects.objects_val->EN_data.en_type,
+-                       "hosts_tbl") != 0
+-            || result->objects.objects_val->EN_data.en_cols.en_cols_len < 3)
+-          sprintf (buf, "[cname=%s],%s", name, tablename_val);
+-        else
+-          sprintf (buf, "[cname=%s],%s", NISENTRYVAL(0, 0, result),
+-                   tablename_val);
+-
+-        nis_freeresult (result);
+-        result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+-      }
+-      if (result == NULL)
++  nis_result *result;
++  char buf[strlen (name) + 10 + tablename_len];
++  int olderr = errno;
++
++  /* Search at first in the alias list, and use the correct name
++     for the next search.  */
++  snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
++  result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++
++  if (result != NULL)
++    {
++      char *bufptr = buf;
++
++      /* If we did not find it, try it as original name. But if the
++       database is correct, we should find it in the first case, too.  */
++      if ((result->status != NIS_SUCCESS
++         && result->status != NIS_S_SUCCESS)
++        || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
++        || strcmp (result->objects.objects_val->EN_data.en_type,
++                   "hosts_tbl") != 0
++        || result->objects.objects_val->EN_data.en_cols.en_cols_len < 3)
++      snprintf (buf, sizeof (buf), "[cname=%s],%s", name, tablename_val);
++      else
+       {
+-        *errnop = ENOMEM;
+-        return NSS_STATUS_TRYAGAIN;
++        /* We need to allocate a new buffer since there is no
++           guarantee the returned name has a length limit.  */
++        const char *entryval = NISENTRYVAL(0, 0, result);
++        size_t buflen = strlen (entryval) + 10 + tablename_len;
++        bufptr = alloca (buflen);
++        snprintf (bufptr, buflen, "[cname=%s],%s",
++                  entryval, tablename_val);
+       }
+-      retval = niserr2nss (result->status);
+-      if (retval != NSS_STATUS_SUCCESS)
+-        {
+-          if (retval == NSS_STATUS_TRYAGAIN)
+-            {
+-            *errnop = errno;
+-              *herrnop = NETDB_INTERNAL;
+-            }
+-        else
+-          __set_errno (olderr);
+-        nis_freeresult (result);
+-          return retval;
+-        }
+-
+-      parse_res = _nss_nisplus_parse_hostent (result, af, host, buffer,
+-                                            buflen, errnop, flags);
+       nis_freeresult (result);
++      result = nis_list (bufptr, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++    }
+-      if (parse_res > 0)
+-      return NSS_STATUS_SUCCESS;
++  if (result == NULL)
++    {
++      *errnop = ENOMEM;
++      return NSS_STATUS_TRYAGAIN;
++    }
+-      *herrnop = NETDB_INTERNAL;
+-      if (parse_res == -1)
++  retval = niserr2nss (result->status);
++  if (__builtin_expect (retval != NSS_STATUS_SUCCESS, 0))
++    {
++      if (retval == NSS_STATUS_TRYAGAIN)
+       {
+-        *errnop = ERANGE;
+-        return NSS_STATUS_TRYAGAIN;
++        *errnop = errno;
++        *herrnop = NETDB_INTERNAL;
+       }
+       else
+-      {
+-        __set_errno (olderr);
+-        return NSS_STATUS_NOTFOUND;
+-      }
++      __set_errno (olderr);
++      nis_freeresult (result);
++      return retval;
++    }
++
++  parse_res = _nss_nisplus_parse_hostent (result, af, host, buffer,
++                                        buflen, errnop, flags);
++
++  nis_freeresult (result);
++
++  if (parse_res > 0)
++    return NSS_STATUS_SUCCESS;
++
++  *herrnop = NETDB_INTERNAL;
++  if (parse_res == -1)
++    {
++      *errnop = ERANGE;
++      return NSS_STATUS_TRYAGAIN;
+     }
++
++  __set_errno (olderr);
++  return NSS_STATUS_NOTFOUND;
+ }
+ enum nss_status
+@@ -431,17 +453,6 @@ _nss_nisplus_gethostbyname2_r (const cha
+                        ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0));
+ }
+-#if 0
+-enum nss_status
+-_nss_nisplus_getipnodebyname_r (const char *name, int af, int flags,
+-                              struct hostent *result, char *buffer,
+-                              size_t buflen, int *errnop, int *herrnop)
+-{
+-  return internal_gethostbyname2_r (name, af, result, buffer, buflen,
+-                                  errnop, herrnop, flags);
+-}
+-#endif
+-
+ enum nss_status
+ _nss_nisplus_gethostbyname_r (const char *name, struct hostent *host,
+                             char *buffer, size_t buflen, int *errnop,
+@@ -469,62 +480,63 @@ _nss_nisplus_gethostbyaddr_r (const void
+ {
+   if (tablename_val == NULL)
+     {
++      __libc_lock_lock (lock);
++
+       enum nss_status status = _nss_create_tablename (errnop);
++      __libc_lock_unlock (lock);
++
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+     }
+   if (addr == NULL)
+     return NSS_STATUS_NOTFOUND;
+-  else
++
++  char buf[24 + tablename_len];
++  int retval, parse_res;
++  int olderr = errno;
++
++  snprintf (buf, sizeof (buf), "[addr=%s],%s",
++         inet_ntoa (*(const struct in_addr *) addr), tablename_val);
++  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++
++  if (result == NULL)
+     {
+-      nis_result *result;
+-      char buf[255 + tablename_len];
+-      int retval, parse_res;
+-      int olderr = errno;
+-
+-      sprintf (buf, "[addr=%s],%s",
+-             inet_ntoa (*(const struct in_addr *) addr), tablename_val);
+-      result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++      __set_errno (ENOMEM);
++      return NSS_STATUS_TRYAGAIN;
++    }
+-      if (result == NULL)
++  retval = niserr2nss (result->status);
++  if (__builtin_expect (retval != NSS_STATUS_SUCCESS, 0))
++    {
++      if (retval == NSS_STATUS_TRYAGAIN)
+       {
+-        __set_errno (ENOMEM);
+-        return NSS_STATUS_TRYAGAIN;
++        *errnop = errno;
++        *herrnop = NETDB_INTERNAL;
+       }
+-      retval = niserr2nss (result->status);
+-      if (retval != NSS_STATUS_SUCCESS)
+-        {
+-          if (retval == NSS_STATUS_TRYAGAIN)
+-            {
+-            *errnop = errno;
+-              *herrnop = NETDB_INTERNAL;
+-            }
+-        else
+-          __set_errno (olderr);
+-        nis_freeresult (result);
+-          return retval;
+-        }
+-
+-      parse_res = _nss_nisplus_parse_hostent (result, af, host,
+-                                            buffer, buflen, errnop,
+-                   ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0));
++      else
++      __set_errno (olderr);
+       nis_freeresult (result);
++      return retval;
++    }
+-      if (parse_res > 0)
+-      return NSS_STATUS_SUCCESS;
++  parse_res = _nss_nisplus_parse_hostent (result, af, host,
++                                        buffer, buflen, errnop,
++                                        ((_res.options & RES_USE_INET6)
++                                         ? AI_V4MAPPED : 0));
++  nis_freeresult (result);
+-      *herrnop = NETDB_INTERNAL;
+-      if (parse_res == -1)
+-      {
+-        *errnop = ERANGE;
+-        return NSS_STATUS_TRYAGAIN;
+-      }
+-      else
+-      {
+-        __set_errno (olderr);
+-        return NSS_STATUS_NOTFOUND;
+-      }
++  if (parse_res > 0)
++    return NSS_STATUS_SUCCESS;
++
++  *herrnop = NETDB_INTERNAL;
++  if (parse_res == -1)
++    {
++      *errnop = ERANGE;
++      return NSS_STATUS_TRYAGAIN;
+     }
++
++  __set_errno (olderr);
++  return NSS_STATUS_NOTFOUND;
+ }
+--- libc/nis/nss_nisplus/nisplus-netgrp.c      10 Sep 2005 03:18:49 -0000      1.15
++++ libc/nis/nss_nisplus/nisplus-netgrp.c      3 Dec 2005 22:11:34 -0000       1.16
+@@ -150,15 +150,14 @@ internal_endnetgrent (struct __netgrent 
+ enum nss_status
+ _nss_nisplus_setnetgrent (const char *group, struct __netgrent *netgrp)
+ {
+-  enum nss_status status;
+-  char buf[strlen (group) + 30];
++  char buf[strlen (group) + 25];
+   if (group == NULL || group[0] == '\0')
+     return NSS_STATUS_UNAVAIL;
+-  status = NSS_STATUS_SUCCESS;
++  enum nss_status status = NSS_STATUS_SUCCESS;
+-  sprintf (buf, "[name=%s],netgroup.org_dir", group);
++  snprintf (buf, sizeof (buf), "[name=%s],netgroup.org_dir", group);
+   netgrp->data = (char *) nis_list (buf, EXPAND_NAME, NULL, NULL);
+--- libc/nis/nss_nisplus/nisplus-network.c     25 Sep 2003 19:44:20 -0000      1.19
++++ libc/nis/nss_nisplus/nisplus-network.c     3 Dec 2005 22:35:12 -0000       1.21
+@@ -17,15 +17,16 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+-#include <nss.h>
+-#include <netdb.h>
+-#include <errno.h>
++#include <atomic.h>
+ #include <ctype.h>
++#include <errno.h>
++#include <netdb.h>
++#include <nss.h>
+ #include <stdint.h>
+ #include <string.h>
+ #include <arpa/inet.h>
+-#include <bits/libc-lock.h>
+ #include <rpcsvc/nis.h>
++#include <bits/libc-lock.h>
+ #include "nss-nisplus.h"
+@@ -44,12 +45,10 @@ static u_long tablename_len;
+ static int
+ _nss_nisplus_parse_netent (nis_result *result, struct netent *network,
+-                          char *buffer, size_t buflen, int *errnop)
++                         char *buffer, size_t buflen, int *errnop)
+ {
+   char *first_unused = buffer;
+   size_t room_left = buflen;
+-  unsigned int i;
+-  char *p, *line;
+   if (result == NULL)
+     return 0;
+@@ -61,7 +60,7 @@ _nss_nisplus_parse_netent (nis_result *r
+       || result->objects.objects_val[0].EN_data.en_cols.en_cols_len < 3)
+     return 0;
+-  if (NISENTRYLEN(0, 0, result) >= room_left)
++  if (NISENTRYLEN (0, 0, result) >= room_left)
+     {
+       /* The line is too long for our buffer.  */
+     no_more_room:
+@@ -69,7 +68,7 @@ _nss_nisplus_parse_netent (nis_result *r
+       return -1;
+     }
+-  strncpy (first_unused, NISENTRYVAL(0, 0, result),
++  strncpy (first_unused, NISENTRYVAL (0, 0, result),
+            NISENTRYLEN (0, 0, result));
+   first_unused[NISENTRYLEN (0, 0, result)] = '\0';
+   network->n_name = first_unused;
+@@ -77,10 +76,10 @@ _nss_nisplus_parse_netent (nis_result *r
+   first_unused += strlen (first_unused) +1;
+   network->n_addrtype = 0;
+   network->n_net = inet_network (NISENTRYVAL (0, 2, result));
+-  p = first_unused;
++  char *p = first_unused;
+-  line = p;
+-  for (i = 0; i < result->objects.objects_len; ++i)
++  char *line = p;
++  for (unsigned int i = 0; i < result->objects.objects_len; ++i)
+     {
+       if (strcmp (NISENTRYVAL (i, 1, result), network->n_name) != 0)
+         {
+@@ -107,12 +106,12 @@ _nss_nisplus_parse_netent (nis_result *r
+   room_left -= (2 * sizeof (char *));
+   network->n_aliases[0] = NULL;
+-  i = 0;
++  unsigned int i = 0;
+   while (*line != '\0')
+     {
+       /* Skip leading blanks.  */
+       while (isspace (*line))
+-        line++;
++        ++line;
+       if (*line == '\0')
+         break;
+@@ -133,7 +132,7 @@ _nss_nisplus_parse_netent (nis_result *r
+           ++i;
+         }
+       else
+-        network->n_aliases[i+1] = NULL;
++        network->n_aliases[i + 1] = NULL;
+     }
+   return 1;
+@@ -144,19 +143,26 @@ _nss_create_tablename (int *errnop)
+ {
+   if (tablename_val == NULL)
+     {
+-      char buf [40 + strlen (nis_local_directory ())];
+-      char *p;
++      const char *local_dir = nis_local_directory ();
++      size_t local_dir_len = strlen (local_dir);
++      static const char prefix[] = "networks.org_dir.";
+-      p = __stpcpy (buf, "networks.org_dir.");
+-      p = __stpcpy (p, nis_local_directory ());
+-      tablename_val = __strdup (buf);
+-      if (tablename_val == NULL)
++      char *p = malloc (sizeof (prefix) + local_dir_len);
++      if (p == NULL)
+       {
+         *errnop = errno;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      tablename_len = strlen (tablename_val);
++
++      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
++
++      tablename_len = sizeof (prefix) - 1 + local_dir_len;
++
++      atomic_write_barrier ();
++
++      tablename_val = p;
+     }
++
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -164,16 +170,20 @@ enum nss_status
+ _nss_nisplus_setnetent (int stayopen)
+ {
+   enum nss_status status = NSS_STATUS_SUCCESS;
+-  int err;
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   if (tablename_val == NULL)
+-    status = _nss_create_tablename (&err);
++    {
++      int err;
++      status = _nss_create_tablename (&err);
++    }
+   __libc_lock_unlock (lock);
+@@ -185,9 +195,11 @@ _nss_nisplus_endnetent (void)
+ {
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   __libc_lock_unlock (lock);
+@@ -220,9 +232,7 @@ internal_nisplus_getnetent_r (struct net
+         result = nis_first_entry (tablename_val);
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           {
+-            int retval;
+-
+-            retval = niserr2nss (result->status);
++            int retval = niserr2nss (result->status);
+             nis_freeresult (result);
+             result = NULL;
+             if (retval == NSS_STATUS_TRYAGAIN)
+@@ -237,16 +247,12 @@ internal_nisplus_getnetent_r (struct net
+       }
+       else
+       {
+-        nis_result *res;
+-
+-        res = nis_next_entry (tablename_val, &result->cookie);
++        nis_result *res = nis_next_entry (tablename_val, &result->cookie);
+         saved_res = result;
+         result = res;
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           {
+-            int retval;
+-
+-            retval = niserr2nss (result->status);
++            int retval = niserr2nss (result->status);
+             nis_freeresult (result);
+             result = saved_res;
+             if (retval == NSS_STATUS_TRYAGAIN)
+@@ -266,7 +272,8 @@ internal_nisplus_getnetent_r (struct net
+           return NSS_STATUS_TRYAGAIN;
+         }
+-    } while (!parse_res);
++    }
++  while (!parse_res);
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -296,8 +303,12 @@ _nss_nisplus_getnetbyname_r (const char 
+   if (tablename_val == NULL)
+     {
++      __libc_lock_lock (lock);
++
+       enum nss_status status = _nss_create_tablename (errnop);
++      __libc_lock_unlock (lock);
++
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+     }
+@@ -308,76 +319,82 @@ _nss_nisplus_getnetbyname_r (const char 
+       *herrnop = NETDB_INTERNAL;
+       return NSS_STATUS_UNAVAIL;
+     }
+-  else
+-    {
+-      nis_result *result;
+-      char buf[strlen (name) + 255 + tablename_len];
+-      int olderr = errno;
+-
+-      /* Search at first in the alias list, and use the correct name
+-       for the next search */
+-      sprintf (buf, "[name=%s],%s", name, tablename_val);
+-      result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
+-      if (result != NULL)
+-      {
+-        /* If we do not find it, try it as original name. But if the
+-           database is correct, we should find it in the first case, too */
+-        if ((result->status != NIS_SUCCESS
+-             && result->status != NIS_S_SUCCESS)
+-            || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
+-            || strcmp (result->objects.objects_val[0].EN_data.en_type,
+-                       "networks_tbl") != 0
+-            || (result->objects.objects_val[0].EN_data.en_cols.en_cols_len
+-                < 3))
+-          sprintf (buf, "[cname=%s],%s", name, tablename_val);
+-        else
+-          sprintf (buf, "[cname=%s],%s", NISENTRYVAL (0, 0, result),
+-                   tablename_val);
++  nis_result *result;
++  char buf[strlen (name) + 10 + tablename_len];
++  int olderr = errno;
++
++  /* Search at first in the alias list, and use the correct name
++     for the next search */
++  snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
++  result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
+-        nis_freeresult (result);
+-        result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
+-      }
++  if (result != NULL)
++    {
++      char *bufptr = buf;
+-      if (result == NULL)
+-      {
+-        __set_errno (ENOMEM);
+-        return NSS_STATUS_TRYAGAIN;
+-      }
+-      retval = niserr2nss (result->status);
+-      if (retval != NSS_STATUS_SUCCESS)
++      /* If we do not find it, try it as original name. But if the
++       database is correct, we should find it in the first case, too */
++      if ((result->status != NIS_SUCCESS
++         && result->status != NIS_S_SUCCESS)
++        || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
++        || strcmp (result->objects.objects_val[0].EN_data.en_type,
++                   "networks_tbl") != 0
++        || (result->objects.objects_val[0].EN_data.en_cols.en_cols_len
++            < 3))
++      snprintf (buf, sizeof (buf), "[cname=%s],%s", name, tablename_val);
++      else
+       {
+-        if (retval == NSS_STATUS_TRYAGAIN)
+-          {
+-            *errnop = errno;
+-            *herrnop = NETDB_INTERNAL;
+-          }
+-        else
+-          __set_errno (olderr);
+-        nis_freeresult (result);
+-        return retval;
++        /* We need to allocate a new buffer since there is no
++           guarantee the returned name has a length limit.  */
++        const char *entryval = NISENTRYVAL (0, 0, result);
++        size_t buflen = strlen (entryval) + 10 + tablename_len;
++        bufptr = alloca (buflen);
++        snprintf (bufptr, buflen, "[cname=%s],%s",
++                  entryval, tablename_val);
+       }
+-      parse_res = _nss_nisplus_parse_netent (result, network, buffer, buflen,
+-                                           errnop);
+-
+       nis_freeresult (result);
++      result = nis_list (bufptr, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
++    }
+-      if (parse_res > 0)
+-      return NSS_STATUS_SUCCESS;
++  if (result == NULL)
++    {
++      __set_errno (ENOMEM);
++      return NSS_STATUS_TRYAGAIN;
++    }
+-      *herrnop = NETDB_INTERNAL;
+-      if (parse_res == -1)
++  retval = niserr2nss (result->status);
++  if (__builtin_expect (retval != NSS_STATUS_SUCCESS, 0))
++    {
++      if (retval == NSS_STATUS_TRYAGAIN)
+       {
+-        *errnop = ERANGE;
+-        return NSS_STATUS_TRYAGAIN;
++        *errnop = errno;
++        *herrnop = NETDB_INTERNAL;
+       }
+       else
+-      {
+-        __set_errno (olderr);
+-        return NSS_STATUS_NOTFOUND;
+-      }
++      __set_errno (olderr);
++      nis_freeresult (result);
++      return retval;
++    }
++
++  parse_res = _nss_nisplus_parse_netent (result, network, buffer, buflen,
++                                       errnop);
++
++  nis_freeresult (result);
++
++  if (parse_res > 0)
++    return NSS_STATUS_SUCCESS;
++
++  *herrnop = NETDB_INTERNAL;
++  if (parse_res == -1)
++    {
++      *errnop = ERANGE;
++      return NSS_STATUS_TRYAGAIN;
+     }
++
++  __set_errno (olderr);
++  return NSS_STATUS_NOTFOUND;
+ }
+ /* XXX type is ignored, SUN's NIS+ table doesn't support it */
+@@ -388,39 +405,39 @@ _nss_nisplus_getnetbyaddr_r (uint32_t ad
+ {
+   if (tablename_val == NULL)
+     {
++      __libc_lock_lock (lock);
++
+       enum nss_status status = _nss_create_tablename (errnop);
++      __libc_lock_unlock (lock);
++
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+     }
+   {
+-    int parse_res, retval;
+-    nis_result *result;
+-    char buf[1024 + tablename_len];
+-    struct in_addr in;
+-    char buf2[256];
+-    int b2len;
++    char buf[27 + tablename_len];
++    char buf2[18];
+     int olderr = errno;
+-    in = inet_makeaddr (addr, 0);
++    struct in_addr in = inet_makeaddr (addr, 0);
+     strcpy (buf2, inet_ntoa (in));
+-    b2len = strlen (buf2);
++    size_t b2len = strlen (buf2);
+     while (1)
+       {
+-      sprintf (buf, "[addr=%s],%s", buf2, tablename_val);
+-      result = nis_list (buf, EXPAND_NAME, NULL, NULL);
++      snprintf (buf, sizeof (buf), "[addr=%s],%s", buf2, tablename_val);
++      nis_result *result = nis_list (buf, EXPAND_NAME, NULL, NULL);
+       if (result == NULL)
+         {
+           __set_errno (ENOMEM);
+           return NSS_STATUS_TRYAGAIN;
+         }
+-      retval = niserr2nss (result->status);
+-      if (retval != NSS_STATUS_SUCCESS)
++      enum nss_status retval = niserr2nss (result->status);
++      if (__builtin_expect (retval != NSS_STATUS_SUCCESS, 0))
+         {
+-          if (buf2[b2len -2] == '.' && buf2[b2len -1] == '0')
++          if (b2len > 2 && buf2[b2len - 2] == '.' && buf2[b2len - 1] == '0')
+             {
+               /* Try again, but with trailing dot(s)
+                  removed (one by one) */
+@@ -428,8 +445,6 @@ _nss_nisplus_getnetbyaddr_r (uint32_t ad
+               b2len -= 2;
+               continue;
+             }
+-          else
+-            return NSS_STATUS_NOTFOUND;
+           if (retval == NSS_STATUS_TRYAGAIN)
+             {
+@@ -442,8 +457,8 @@ _nss_nisplus_getnetbyaddr_r (uint32_t ad
+           return retval;
+         }
+-      parse_res = _nss_nisplus_parse_netent (result, network, buffer,
+-                                             buflen, errnop);
++      int parse_res = _nss_nisplus_parse_netent (result, network, buffer,
++                                                 buflen, errnop);
+       nis_freeresult (result);
+--- libc/nis/nss_nisplus/nisplus-proto.c       25 Sep 2003 19:44:20 -0000      1.19
++++ libc/nis/nss_nisplus/nisplus-proto.c       3 Dec 2005 19:33:09 -0000       1.20
+@@ -17,13 +17,14 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+-#include <nss.h>
+-#include <errno.h>
++#include <atomic.h>
+ #include <ctype.h>
++#include <errno.h>
+ #include <netdb.h>
++#include <nss.h>
+ #include <string.h>
+-#include <bits/libc-lock.h>
+ #include <rpcsvc/nis.h>
++#include <bits/libc-lock.h>
+ #include "nss-nisplus.h"
+@@ -141,19 +142,26 @@ _nss_create_tablename (int *errnop)
+ {
+   if (tablename_val == NULL)
+     {
+-      char buf [40 + strlen (nis_local_directory ())];
+-      char *p;
++      const char *local_dir = nis_local_directory ();
++      size_t local_dir_len = strlen (local_dir);
++      static const char prefix[] = "protocols.org_dir.";
+-      p = __stpcpy (buf, "protocols.org_dir.");
+-      p = __stpcpy (p, nis_local_directory ());
+-      tablename_val = __strdup (buf);
+-      if (tablename_val == NULL)
++      char *p = malloc (sizeof (prefix) + local_dir_len);
++      if (p == NULL)
+       {
+         *errnop = errno;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      tablename_len = strlen (tablename_val);
++
++      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
++
++      tablename_len = sizeof (prefix) - 1 + local_dir_len;
++
++      atomic_write_barrier ();
++
++      tablename_val = p;
+     }
++
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -164,9 +172,11 @@ _nss_nisplus_setprotoent (int stayopen)
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   if (tablename_val == NULL)
+     {
+@@ -184,9 +194,11 @@ _nss_nisplus_endprotoent (void)
+ {
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   __libc_lock_unlock (lock);
+@@ -221,11 +233,8 @@ internal_nisplus_getprotoent_r (struct p
+       }
+       else
+       {
+-        nis_result *res;
+-
+         saved_res = result;
+-        res = nis_next_entry (tablename_val, &result->cookie);
+-        result = res;
++        result = nis_next_entry (tablename_val, &result->cookie);
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           {
+@@ -277,79 +286,91 @@ _nss_nisplus_getprotobyname_r (const cha
+   if (tablename_val == NULL)
+     {
++      __libc_lock_lock (lock);
++
+       enum nss_status status = _nss_create_tablename (errnop);
++      __libc_lock_unlock (lock);
++
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+     }
+   if (name == NULL)
+     return NSS_STATUS_NOTFOUND;
+-  else
+-    {
+-      nis_result *result;
+-      char buf[strlen (name) + 255 + tablename_len];
+-      int olderr = errno;
+-
+-      /* Search at first in the alias list, and use the correct name
+-         for the next search */
+-      sprintf (buf, "[name=%s],%s", name, tablename_val);
+-      result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+-      if (result != NULL)
+-      {
+-        /* If we do not find it, try it as original name. But if the
+-           database is correct, we should find it in the first case, too */
+-        if ((result->status != NIS_SUCCESS
+-             && result->status != NIS_S_SUCCESS)
+-            || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
+-            || strcmp (result->objects.objects_val->EN_data.en_type,
+-                       "protocols_tbl") != 0
+-            || result->objects.objects_val->EN_data.en_cols.en_cols_len < 3)
+-          sprintf (buf, "[cname=%s],%s", name, tablename_val);
+-        else
+-          sprintf (buf, "[cname=%s],%s", NISENTRYVAL (0, 0, result),
+-                   tablename_val);
++  char buf[strlen (name) + 10 + tablename_len];
++  int olderr = errno;
+-        nis_freeresult (result);
+-        result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+-      }
++  /* Search at first in the alias list, and use the correct name
++     for the next search */
++  snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
++  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+-      if (result == NULL)
++  if (result != NULL)
++    {
++      char *bufptr = buf;
++
++      /* If we did not find it, try it as original name. But if the
++       database is correct, we should find it in the first case, too */
++      if ((result->status != NIS_SUCCESS
++         && result->status != NIS_S_SUCCESS)
++        || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
++        || strcmp (result->objects.objects_val->EN_data.en_type,
++                       "protocols_tbl") != 0
++        || result->objects.objects_val->EN_data.en_cols.en_cols_len < 3)
++      snprintf (buf, sizeof (buf), "[cname=%s],%s", name, tablename_val);
++      else
+       {
+-        __set_errno (ENOMEM);
+-        return NSS_STATUS_TRYAGAIN;
++        /* We need to allocate a new buffer since there is no
++           guarantee the returned name has a length limit.  */
++        const char *entryval = NISENTRYVAL (0, 0, result);
++        size_t buflen = strlen (entryval) + 10 + tablename_len;
++        bufptr = alloca (buflen);
++        snprintf (bufptr, buflen, "[cname=%s],%s",
++                  entryval, tablename_val);
+       }
+-      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+-      {
+-        enum nss_status status = niserr2nss (result->status);
+-        __set_errno (olderr);
++      nis_freeresult (result);
++      result = nis_list (bufptr, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++    }
+-        nis_freeresult (result);
+-        return status;
+-      }
++  if (result == NULL)
++    {
++      __set_errno (ENOMEM);
++      return NSS_STATUS_TRYAGAIN;
++    }
+-      parse_res = _nss_nisplus_parse_protoent (result, proto, buffer, buflen,
+-                                             errnop);
++  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
++    {
++      enum nss_status status = niserr2nss (result->status);
++
++      __set_errno (olderr);
+       nis_freeresult (result);
++      return status;
++    }
+-      if (parse_res < 1)
++  parse_res = _nss_nisplus_parse_protoent (result, proto, buffer, buflen,
++                                         errnop);
++
++  nis_freeresult (result);
++
++  if (parse_res < 1)
++    {
++      if (parse_res == -1)
+       {
+-        if (parse_res == -1)
+-          {
+-            *errnop = ERANGE;
+-            return NSS_STATUS_TRYAGAIN;
+-          }
+-        else
+-          {
+-            __set_errno (olderr);
+-            return NSS_STATUS_NOTFOUND;
+-          }
++        *errnop = ERANGE;
++        return NSS_STATUS_TRYAGAIN;
++      }
++      else
++      {
++        __set_errno (olderr);
++        return NSS_STATUS_NOTFOUND;
+       }
+-      return NSS_STATUS_SUCCESS;
+     }
++
++  return NSS_STATUS_SUCCESS;
+ }
+ enum nss_status
+@@ -358,55 +379,57 @@ _nss_nisplus_getprotobynumber_r (const i
+ {
+   if (tablename_val == NULL)
+     {
++      __libc_lock_lock (lock);
++
+       enum nss_status status = _nss_create_tablename (errnop);
++      __libc_lock_unlock (lock);
++
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+     }
+-  {
+-    int parse_res;
+-    nis_result *result;
+-    char buf[46 + tablename_len];
+-    int olderr = errno;
+-
+-    sprintf (buf, "[number=%d],%s", number, tablename_val);
+-
+-    result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
+-
+-    if (result == NULL)
+-      {
+-      __set_errno (ENOMEM);
+-      return NSS_STATUS_TRYAGAIN;
+-      }
+-    if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+-      {
+-      enum nss_status status = niserr2nss (result->status);
++  char buf[12 + 3 * sizeof (number) + tablename_len];
++  int olderr = errno;
+-      __set_errno (olderr);
++  snprintf (buf, sizeof (buf), "[number=%d],%s", number, tablename_val);
+-      nis_freeresult (result);
+-      return status;
+-      }
++  nis_result *result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
+-    parse_res = _nss_nisplus_parse_protoent (result, proto, buffer, buflen,
+-                                           errnop);
++  if (result == NULL)
++    {
++      __set_errno (ENOMEM);
++      return NSS_STATUS_TRYAGAIN;
++    }
+-    nis_freeresult (result);
++  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
++    {
++      enum nss_status status = niserr2nss (result->status);
++
++      __set_errno (olderr);
++
++      nis_freeresult (result);
++      return status;
++    }
+-    if (parse_res < 1)
+-      {
+-      if (parse_res == -1)
+-        {
+-          *errnop = ERANGE;
+-          return NSS_STATUS_TRYAGAIN;
+-        }
+-      else
+-        {
+-          __set_errno (olderr);
+-          return NSS_STATUS_NOTFOUND;
+-        }
+-      }
+-    return NSS_STATUS_SUCCESS;
+-  }
++  int parse_res = _nss_nisplus_parse_protoent (result, proto, buffer, buflen,
++                                             errnop);
++
++  nis_freeresult (result);
++
++  if (parse_res < 1)
++    {
++      if (parse_res == -1)
++      {
++        *errnop = ERANGE;
++        return NSS_STATUS_TRYAGAIN;
++      }
++      else
++      {
++        __set_errno (olderr);
++        return NSS_STATUS_NOTFOUND;
++      }
++    }
++
++  return NSS_STATUS_SUCCESS;
+ }
+--- libc/nis/nss_nisplus/nisplus-publickey.c   25 Sep 2003 19:44:20 -0000      1.16
++++ libc/nis/nss_nisplus/nisplus-publickey.c   3 Dec 2005 22:08:17 -0000       1.17
+@@ -37,7 +37,7 @@ _nss_nisplus_getpublickey (const char *n
+ {
+   nis_result *res;
+   enum nss_status retval;
+-  char buf[NIS_MAXNAMELEN+2];
++  char buf[NIS_MAXNAMELEN + 2];
+   size_t slen;
+   char *domain, *cptr;
+   int len;
+@@ -120,7 +120,7 @@ _nss_nisplus_getsecretkey (const char *n
+ {
+   nis_result *res;
+   enum nss_status retval;
+-  char buf[NIS_MAXNAMELEN+2];
++  char buf[NIS_MAXNAMELEN + 2];
+   size_t slen;
+   char *domain, *cptr;
+   int len;
+@@ -154,7 +154,7 @@ _nss_nisplus_getsecretkey (const char *n
+       buf[slen] = '\0';
+     }
+-  res = nis_list (buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
++  res = nis_list (buf, USE_DGRAM | NO_AUTHINFO | FOLLOW_LINKS | FOLLOW_PATH,
+                 NULL, NULL);
+   if (res == NULL)
+@@ -242,9 +242,9 @@ _nss_nisplus_netname2user (char netname[
+ {
+   char *domain;
+   nis_result *res;
+-  char sname[NIS_MAXNAMELEN+2]; /*  search criteria + table name */
++  char sname[NIS_MAXNAMELEN + 2]; /*  search criteria + table name */
+   size_t slen;
+-  char principal[NIS_MAXNAMELEN+1];
++  char principal[NIS_MAXNAMELEN + 1];
+   int len;
+   /* 1.  Get home domain of user. */
+@@ -255,10 +255,6 @@ _nss_nisplus_netname2user (char netname[
+   ++domain;  /* skip '@' */
+   /* 2.  Get user's nisplus principal name.  */
+-  if ((strlen (netname) + strlen (domain)+45) >
+-      (size_t) NIS_MAXNAMELEN)
+-    return NSS_STATUS_UNAVAIL;
+-
+   slen = snprintf (sname, NIS_MAXNAMELEN,
+                  "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
+                  netname, domain);
+@@ -339,8 +335,9 @@ _nss_nisplus_netname2user (char netname[
+       return NSS_STATUS_UNAVAIL;
+     }
+-  slen = sprintf (sname, "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
+-                principal, domain);
++  slen = snprintf (sname, sizeof  (sname),
++                 "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
++                 principal, domain);
+   if (sname[slen - 1] != '.')
+     {
+--- libc/nis/nss_nisplus/nisplus-pwd.c 25 Sep 2003 19:44:20 -0000      1.17
++++ libc/nis/nss_nisplus/nisplus-pwd.c 3 Dec 2005 20:39:34 -0000       1.20
+@@ -17,6 +17,7 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
++#include <atomic.h>
+ #include <nss.h>
+ #include <errno.h>
+ #include <pwd.h>
+@@ -30,27 +31,39 @@
+ __libc_lock_define_initialized (static, lock)
+ static nis_result *result;
+-static nis_name tablename_val;
+-static u_long tablename_len;
++nis_name pwd_tablename_val attribute_hidden;
++size_t pwd_tablename_len attribute_hidden;
+-static enum nss_status
+-_nss_create_tablename (int *errnop)
++enum nss_status
++_nss_pwd_create_tablename (int *errnop)
+ {
+-  if (tablename_val == NULL)
++  if (pwd_tablename_val == NULL)
+     {
+-      char buf [40 + strlen (nis_local_directory ())];
+-      char *p;
++      const char *local_dir = nis_local_directory ();
++      size_t local_dir_len = strlen (local_dir);
++      static const char prefix[] = "passwd.org_dir.";
+-      p = __stpcpy (buf, "passwd.org_dir.");
+-      p = __stpcpy (p, nis_local_directory ());
+-      tablename_val = __strdup (buf);
+-      if (tablename_val == NULL)
++      char *p = malloc (sizeof (prefix) + local_dir_len);
++      if (p == NULL)
+       {
+         *errnop = errno;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      tablename_len = strlen (tablename_val);
++
++      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
++
++      pwd_tablename_len = sizeof (prefix) - 1 + local_dir_len;
++
++      atomic_write_barrier ();
++
++      if (atomic_compare_and_exchange_bool_acq (&pwd_tablename_val, p, NULL))
++      {
++        /* Another thread already installed the value.  */
++        free (p);
++        pwd_tablename_len = strlen (pwd_tablename_val);
++      }
+     }
++
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -59,16 +72,20 @@ enum nss_status
+ _nss_nisplus_setpwent (int stayopen)
+ {
+   enum nss_status status = NSS_STATUS_SUCCESS;
+-  int err;
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+-  if (tablename_val == NULL)
+-    status = _nss_create_tablename (&err);
++  if (pwd_tablename_val == NULL)
++    {
++      int err;
++      status = _nss_pwd_create_tablename (&err);
++    }
+   __libc_lock_unlock (lock);
+@@ -80,9 +97,11 @@ _nss_nisplus_endpwent (void)
+ {
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   __libc_lock_unlock (lock);
+@@ -103,25 +122,22 @@ internal_nisplus_getpwent_r (struct pass
+       if (result == NULL)
+       {
+         saved_res = NULL;
+-          if (tablename_val == NULL)
++          if (pwd_tablename_val == NULL)
+           {
+-            enum nss_status status = _nss_create_tablename (errnop);
++            enum nss_status status = _nss_pwd_create_tablename (errnop);
+             if (status != NSS_STATUS_SUCCESS)
+               return status;
+           }
+-        result = nis_first_entry (tablename_val);
++        result = nis_first_entry (pwd_tablename_val);
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           return niserr2nss (result->status);
+       }
+       else
+       {
+-        nis_result *res;
+-
+         saved_res = result;
+-        res = nis_next_entry (tablename_val, &result->cookie);
+-        result = res;
++        result = nis_next_entry (pwd_tablename_val, &result->cookie);
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           {
+             nis_freeresult (saved_res);
+@@ -131,19 +147,18 @@ internal_nisplus_getpwent_r (struct pass
+       parse_res = _nss_nisplus_parse_pwent (result, pw, buffer,
+                                           buflen, errnop);
+-      if (parse_res == -1)
++      if (__builtin_expect (parse_res == -1, 0))
+       {
+         nis_freeresult (result);
+         result = saved_res;
+         *errnop = ERANGE;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      else
+-      {
+-        if (saved_res)
+-          nis_freeresult (saved_res);
+-      }
+-    } while (!parse_res);
++
++      if (saved_res)
++      nis_freeresult (saved_res);
++    }
++  while (!parse_res);
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -169,9 +184,9 @@ _nss_nisplus_getpwnam_r (const char *nam
+ {
+   int parse_res;
+-  if (tablename_val == NULL)
++  if (pwd_tablename_val == NULL)
+     {
+-      enum nss_status status = _nss_create_tablename (errnop);
++      enum nss_status status = _nss_pwd_create_tablename (errnop);
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+@@ -182,107 +197,107 @@ _nss_nisplus_getpwnam_r (const char *nam
+       *errnop = EINVAL;
+       return NSS_STATUS_UNAVAIL;
+     }
+-  else
+-    {
+-      nis_result *result;
+-      char buf[strlen (name) + 24 + tablename_len];
+-      int olderr = errno;
+-      sprintf (buf, "[name=%s],%s", name, tablename_val);
++  nis_result *result;
++  char buf[strlen (name) + 9 + pwd_tablename_len];
++  int olderr = errno;
+-      result = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++  snprintf (buf, sizeof (buf), "[name=%s],%s", name, pwd_tablename_val);
+-      if (result == NULL)
+-      {
+-        *errnop = ENOMEM;
+-        return NSS_STATUS_TRYAGAIN;
+-      }
+-      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+-      {
+-        enum nss_status status =  niserr2nss (result->status);
++  result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+-        __set_errno (olderr);
++  if (result == NULL)
++    {
++      *errnop = ENOMEM;
++      return NSS_STATUS_TRYAGAIN;
++    }
+-        nis_freeresult (result);
+-        return status;
+-      }
++  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
++    {
++      enum nss_status status =  niserr2nss (result->status);
+-      parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen,
+-                                          errnop);
++      __set_errno (olderr);
+       nis_freeresult (result);
++      return status;
++    }
++
++  parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop);
++
++  nis_freeresult (result);
+-      if (parse_res < 1)
++  if (__builtin_expect (parse_res < 1, 0))
++    {
++      if (parse_res == -1)
+       {
+-        if (parse_res == -1)
+-          {
+-            *errnop = ERANGE;
+-            return NSS_STATUS_TRYAGAIN;
+-          }
+-        else
+-          {
+-            __set_errno (olderr);
+-            return NSS_STATUS_NOTFOUND;
+-          }
++        *errnop = ERANGE;
++        return NSS_STATUS_TRYAGAIN;
++      }
++      else
++      {
++        __set_errno (olderr);
++        return NSS_STATUS_NOTFOUND;
+       }
+-      return NSS_STATUS_SUCCESS;
+     }
++
++  return NSS_STATUS_SUCCESS;
+ }
+ enum nss_status
+ _nss_nisplus_getpwuid_r (const uid_t uid, struct passwd *pw,
+                        char *buffer, size_t buflen, int *errnop)
+ {
+-  if (tablename_val == NULL)
++  if (pwd_tablename_val == NULL)
+     {
+-      enum nss_status status = _nss_create_tablename (errnop);
++      enum nss_status status = _nss_pwd_create_tablename (errnop);
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+     }
+-  {
+-    int parse_res;
+-    nis_result *result;
+-    char buf[100 + tablename_len];
+-    int olderr = errno;
+-
+-    sprintf (buf, "[uid=%lu],%s", (unsigned long int) uid, tablename_val);
+-
+-    result = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+-
+-    if (result == NULL)
+-      {
+-      *errnop = ENOMEM;
+-      return NSS_STATUS_TRYAGAIN;
+-      }
+-    if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+-      {
+-      enum nss_status status = niserr2nss (result->status);
++  int parse_res;
++  nis_result *result;
++  char buf[8 + 3 * sizeof (unsigned long int) + pwd_tablename_len];
++  int olderr = errno;
+-      __set_errno (olderr);
++  snprintf (buf, sizeof (buf), "[uid=%lu],%s",
++          (unsigned long int) uid, pwd_tablename_val);
+-      nis_freeresult (result);
+-      return status;
+-      }
++  result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++
++  if (result == NULL)
++    {
++      *errnop = ENOMEM;
++      return NSS_STATUS_TRYAGAIN;
++    }
+-    parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop);
++  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
++    {
++      enum nss_status status = niserr2nss (result->status);
++
++      __set_errno (olderr);
++
++      nis_freeresult (result);
++      return status;
++    }
+-    nis_freeresult (result);
++  parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop);
+-    if (parse_res < 1)
+-      {
+-      if (parse_res == -1)
+-        {
+-          *errnop = ERANGE;
+-          return NSS_STATUS_TRYAGAIN;
+-        }
+-      else
+-        {
+-          __set_errno (olderr);
+-          return NSS_STATUS_NOTFOUND;
+-        }
+-      }
+-    return NSS_STATUS_SUCCESS;
+-  }
++  nis_freeresult (result);
++
++  if (__builtin_expect (parse_res < 1, 0))
++    {
++      if (parse_res == -1)
++      {
++        *errnop = ERANGE;
++        return NSS_STATUS_TRYAGAIN;
++      }
++      else
++      {
++        __set_errno (olderr);
++        return NSS_STATUS_NOTFOUND;
++      }
++    }
++
++  return NSS_STATUS_SUCCESS;
+ }
+--- libc/nis/nss_nisplus/nisplus-rpc.c 25 Sep 2003 19:44:20 -0000      1.19
++++ libc/nis/nss_nisplus/nisplus-rpc.c 3 Dec 2005 19:54:38 -0000       1.20
+@@ -17,13 +17,14 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+-#include <nss.h>
+-#include <errno.h>
++#include <atomic.h>
+ #include <ctype.h>
++#include <errno.h>
++#include <nss.h>
+ #include <string.h>
+-#include <bits/libc-lock.h>
+ #include <rpc/netdb.h>
+ #include <rpcsvc/nis.h>
++#include <bits/libc-lock.h>
+ #include "nss-nisplus.h"
+@@ -138,19 +139,26 @@ _nss_create_tablename (int *errnop)
+ {
+   if (tablename_val == NULL)
+     {
+-      char buf [40 + strlen (nis_local_directory ())];
+-      char *p;
++      const char *local_dir = nis_local_directory ();
++      size_t local_dir_len = strlen (local_dir);
++      static const char prefix[] = "rpc.org_dir.";
+-      p = __stpcpy (buf, "rpc.org_dir.");
+-      p = __stpcpy (p, nis_local_directory ());
+-      tablename_val = __strdup (buf);
+-      if (tablename_val == NULL)
++      char *p = malloc (sizeof (prefix) + local_dir_len);
++      if (p == NULL)
+       {
+         *errnop = errno;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      tablename_len = strlen (tablename_val);
++
++      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
++
++      tablename_len = sizeof (prefix) - 1 + local_dir_len;
++
++      atomic_write_barrier ();
++
++      tablename_val = p;
+     }
++
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -159,16 +167,20 @@ enum nss_status
+ _nss_nisplus_setrpcent (int stayopen)
+ {
+   enum nss_status status = NSS_STATUS_SUCCESS;
+-  int err;
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   if (tablename_val == NULL)
+-    status = _nss_create_tablename (&err);
++    {
++      int err;
++      status = _nss_create_tablename (&err);
++    }
+   __libc_lock_unlock (lock);
+@@ -180,9 +192,11 @@ _nss_nisplus_endrpcent (void)
+ {
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   __libc_lock_unlock (lock);
+@@ -217,11 +231,8 @@ internal_nisplus_getrpcent_r (struct rpc
+       }
+       else
+       {
+-        nis_result *res;
+-
+         saved_res = result;
+-        res = nis_next_entry (tablename_val, &result->cookie);
+-        result = res;
++        result = nis_next_entry (tablename_val, &result->cookie);
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           {
+             nis_freeresult (saved_res);
+@@ -243,7 +254,8 @@ internal_nisplus_getrpcent_r (struct rpc
+         if (saved_res)
+           nis_freeresult (saved_res);
+       }
+-    } while (!parse_res);
++    }
++  while (!parse_res);
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -271,77 +283,89 @@ _nss_nisplus_getrpcbyname_r (const char 
+   if (tablename_val == NULL)
+     {
++      __libc_lock_lock (lock);
++
+       enum nss_status status = _nss_create_tablename (errnop);
++      __libc_lock_unlock (lock);
++
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+     }
+   if (name == NULL)
+     return NSS_STATUS_NOTFOUND;
+-  else
+-    {
+-      nis_result *result;
+-      char buf[strlen (name) + 255 + tablename_len];
+-      int olderr = errno;
+-
+-      /* Search at first in the alias list, and use the correct name
+-         for the next search */
+-      sprintf (buf, "[name=%s],%s", name, tablename_val);
+-      result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+-      if (result != NULL)
+-      {
+-        /* If we do not find it, try it as original name. But if the
+-           database is correct, we should find it in the first case, too */
+-        if ((result->status != NIS_SUCCESS
+-             && result->status != NIS_S_SUCCESS)
+-            || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
+-            || strcmp (result->objects.objects_val->EN_data.en_type,
+-                       "rpc_tbl") != 0
+-            || result->objects.objects_val->EN_data.en_cols.en_cols_len < 3)
+-          sprintf (buf, "[cname=%s],%s", name, tablename_val);
+-        else
+-          sprintf (buf, "[cname=%s],%s", NISENTRYVAL (0, 0, result),
+-                   tablename_val);
++  char buf[strlen (name) + 10 + tablename_len];
++  int olderr = errno;
+-        nis_freeresult (result);
+-        result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS , NULL, NULL);
+-      }
++  /* Search at first in the alias list, and use the correct name
++     for the next search */
++  snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
++  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+-      if (result == NULL)
++  if (result != NULL)
++    {
++      char *bufptr = buf;
++
++      /* If we did not find it, try it as original name. But if the
++       database is correct, we should find it in the first case, too */
++      if ((result->status != NIS_SUCCESS
++         && result->status != NIS_S_SUCCESS)
++        || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
++        || strcmp (result->objects.objects_val->EN_data.en_type,
++                   "rpc_tbl") != 0
++        || result->objects.objects_val->EN_data.en_cols.en_cols_len < 3)
++      snprintf (buf, sizeof (buf), "[cname=%s],%s", name, tablename_val);
++      else
+       {
+-        *errnop = ENOMEM;
+-        return NSS_STATUS_TRYAGAIN;
++        /* We need to allocate a new buffer since there is no
++           guarantee the returned name has a length limit.  */
++        const char *entryval = NISENTRYVAL (0, 0, result);
++        size_t buflen = strlen (entryval) + 10 + tablename_len;
++        bufptr = alloca (buflen);
++        snprintf (bufptr, buflen, "[cname=%s],%s",
++                  entryval, tablename_val);
+       }
+-      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+-      {
+-        enum nss_status status = niserr2nss (result->status);
+-        __set_errno (olderr);
++      nis_freeresult (result);
++      result = nis_list (bufptr, FOLLOW_PATH | FOLLOW_LINKS , NULL, NULL);
++    }
+-        nis_freeresult (result);
+-        return status;
+-      }
++  if (result == NULL)
++    {
++      *errnop = ENOMEM;
++      return NSS_STATUS_TRYAGAIN;
++    }
+-      parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen,
+-                                           errnop);
++  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
++    {
++      enum nss_status status = niserr2nss (result->status);
++
++      __set_errno (olderr);
+       nis_freeresult (result);
++      return status;
++    }
+-      if (parse_res < 1)
+-      {
+-        if (parse_res == -1)
+-          {
+-            *errnop = ERANGE;
+-            return NSS_STATUS_TRYAGAIN;
+-          }
++  parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen,
++                                           errnop);
+-        __set_errno (olderr);
+-        return NSS_STATUS_NOTFOUND;
++  nis_freeresult (result);
++
++  if (parse_res < 1)
++    {
++      if (parse_res == -1)
++      {
++        *errnop = ERANGE;
++        return NSS_STATUS_TRYAGAIN;
+       }
+-      return NSS_STATUS_SUCCESS;
++
++      __set_errno (olderr);
++      return NSS_STATUS_NOTFOUND;
+     }
++
++  return NSS_STATUS_SUCCESS;
+ }
+ enum nss_status
+@@ -350,55 +374,57 @@ _nss_nisplus_getrpcbynumber_r (const int
+ {
+   if (tablename_val == NULL)
+     {
++      __libc_lock_lock (lock);
++
+       enum nss_status status = _nss_create_tablename (errnop);
++      __libc_lock_unlock (lock);
++
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+     }
+-  {
+-    int parse_res;
+-    nis_result *result;
+-    char buf[100 + tablename_len];
+-    int olderr = errno;
+-
+-    sprintf (buf, "[number=%d],%s", number, tablename_val);
+-
+-    result = nis_list(buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
+-
+-    if (result == NULL)
+-      {
+-      *errnop = ENOMEM;
+-      return NSS_STATUS_TRYAGAIN;
+-      }
+-    if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+-      {
+-      enum nss_status status = niserr2nss (result->status);
++  char buf[12 + 3 * sizeof (number) + tablename_len];
++  int olderr = errno;
+-      __set_errno (olderr);
++  snprintf (buf, sizeof (buf), "[number=%d],%s", number, tablename_val);
+-      nis_freeresult (result);
+-      return status;
+-      }
++  nis_result *result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
++
++  if (result == NULL)
++    {
++      *errnop = ENOMEM;
++      return NSS_STATUS_TRYAGAIN;
++    }
++
++  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS,  0))
++    {
++      enum nss_status status = niserr2nss (result->status);
+-    parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen,
+-                                         errnop);
++      __set_errno (olderr);
++
++      nis_freeresult (result);
++      return status;
++    }
+-    nis_freeresult (result);
++  int parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen,
++                                           errnop);
++
++  nis_freeresult (result);
++
++  if (parse_res < 1)
++    {
++      if (parse_res == -1)
++      {
++        *errnop = ERANGE;
++        return NSS_STATUS_TRYAGAIN;
++      }
++      else
++      {
++        __set_errno (olderr);
++        return NSS_STATUS_NOTFOUND;
++      }
++    }
+-    if (parse_res < 1)
+-      {
+-      if (parse_res == -1)
+-        {
+-          *errnop = ERANGE;
+-          return NSS_STATUS_TRYAGAIN;
+-        }
+-      else
+-        {
+-          __set_errno (olderr);
+-          return NSS_STATUS_NOTFOUND;
+-        }
+-      }
+-    return NSS_STATUS_SUCCESS;
+-  }
++  return NSS_STATUS_SUCCESS;
+ }
+--- libc/nis/nss_nisplus/nisplus-service.c     25 Sep 2003 19:44:20 -0000      1.21
++++ libc/nis/nss_nisplus/nisplus-service.c     3 Dec 2005 20:11:34 -0000       1.22
+@@ -17,13 +17,14 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+-#include <nss.h>
+-#include <errno.h>
++#include <atomic.h>
+ #include <ctype.h>
++#include <errno.h>
+ #include <netdb.h>
++#include <nss.h>
+ #include <string.h>
+-#include <bits/libc-lock.h>
+ #include <rpcsvc/nis.h>
++#include <bits/libc-lock.h>
+ #include "nss-nisplus.h"
+@@ -45,8 +46,6 @@ _nss_nisplus_parse_servent (nis_result *
+ {
+   char *first_unused = buffer;
+   size_t room_left = buflen;
+-  unsigned int i;
+-  char *p, *line;
+   if (result == NULL)
+     return 0;
+@@ -81,10 +80,10 @@ _nss_nisplus_parse_servent (nis_result *
+   first_unused += strlen (first_unused) + 1;
+   serv->s_port = htons (atoi (NISENTRYVAL (0, 3, result)));
+-  p = first_unused;
++  char *p = first_unused;
+-  line = p;
+-  for (i = 0; i < result->objects.objects_len; ++i)
++  char *line = p;
++  for (unsigned int i = 0; i < result->objects.objects_len; ++i)
+     {
+       if (strcmp (NISENTRYVAL (i, 1, result), serv->s_name) != 0)
+         {
+@@ -110,7 +109,7 @@ _nss_nisplus_parse_servent (nis_result *
+   room_left -= (sizeof (char *));
+   serv->s_aliases[0] = NULL;
+-  i = 0;
++  unsigned int i = 0;
+   while (*line != '\0')
+     {
+       /* Skip leading blanks.  */
+@@ -147,19 +146,26 @@ _nss_create_tablename (int *errnop)
+ {
+   if (tablename_val == NULL)
+     {
+-      char buf [40 + strlen (nis_local_directory ())];
+-      char *p;
++      const char *local_dir = nis_local_directory ();
++      size_t local_dir_len = strlen (local_dir);
++      static const char prefix[] = "services.org_dir.";
+-      p = __stpcpy (buf, "services.org_dir.");
+-      p = __stpcpy (p, nis_local_directory ());
+-      tablename_val = __strdup (buf);
+-      if (tablename_val == NULL)
++      char *p = malloc (sizeof (prefix) + local_dir_len);
++      if (p == NULL)
+       {
+         *errnop = errno;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      tablename_len = strlen (tablename_val);
++
++      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
++
++      tablename_len = sizeof (prefix) - 1 + local_dir_len;
++
++      atomic_write_barrier ();
++
++      tablename_val = p;
+     }
++
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -172,9 +178,11 @@ _nss_nisplus_setservent (int stayopen)
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   if (tablename_val == NULL)
+     status = _nss_create_tablename (&err);
+@@ -189,9 +197,11 @@ _nss_nisplus_endservent (void)
+ {
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   __libc_lock_unlock (lock);
+@@ -226,11 +236,8 @@ internal_nisplus_getservent_r (struct se
+       }
+       else
+       {
+-        nis_result *res;
+-
+         saved_res = result;
+-        res = nis_next_entry (tablename_val, &result->cookie);
+-        result = res;
++        result = nis_next_entry (tablename_val, &result->cookie);
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           {
+             nis_freeresult (saved_res);
+@@ -240,7 +247,7 @@ internal_nisplus_getservent_r (struct se
+       parse_res = _nss_nisplus_parse_servent (result, serv, buffer,
+                                             buflen, errnop);
+-      if (parse_res == -1)
++      if (__builtin_expect (parse_res == -1, 0))
+       {
+         nis_freeresult (result);
+         result = saved_res;
+@@ -262,11 +269,9 @@ enum nss_status
+ _nss_nisplus_getservent_r (struct servent *result, char *buffer,
+                          size_t buflen, int *errnop)
+ {
+-  int status;
+-
+   __libc_lock_lock (lock);
+-  status = internal_nisplus_getservent_r (result, buffer, buflen, errnop);
++  int status = internal_nisplus_getservent_r (result, buffer, buflen, errnop);
+   __libc_lock_unlock (lock);
+@@ -278,12 +283,14 @@ _nss_nisplus_getservbyname_r (const char
+                             struct servent *serv,
+                             char *buffer, size_t buflen, int *errnop)
+ {
+-  int parse_res;
+-
+   if (tablename_val == NULL)
+     {
++      __libc_lock_lock (lock);
++
+       enum nss_status status = _nss_create_tablename (errnop);
++      __libc_lock_unlock (lock);
++
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+     }
+@@ -293,72 +300,82 @@ _nss_nisplus_getservbyname_r (const char
+       *errnop = EINVAL;
+       return NSS_STATUS_NOTFOUND;
+     }
+-  else
+-    {
+-      nis_result *result;
+-      char buf[strlen (name) + 255 + tablename_len];
+-      int olderr = errno;
+-
+-      /* Search at first in the alias list, and use the correct name
+-         for the next search */
+-      sprintf (buf, "[name=%s,proto=%s],%s", name, protocol,
+-             tablename_val);
+-      result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+-      if (result != NULL)
++  size_t protocol_len = strlen (protocol);
++  char buf[strlen (name) + protocol_len + 17 + tablename_len];
++  int olderr = errno;
++
++  /* Search at first in the alias list, and use the correct name
++     for the next search */
++  snprintf (buf, sizeof (buf), "[name=%s,proto=%s],%s", name, protocol,
++          tablename_val);
++  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++
++  if (result != NULL)
++    {
++      char *bufptr = buf;
++
++      /* If we did not find it, try it as original name. But if the
++       database is correct, we should find it in the first case, too */
++      if ((result->status != NIS_SUCCESS
++         && result->status != NIS_S_SUCCESS)
++        || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
++        || strcmp (result->objects.objects_val->EN_data.en_type,
++                   "services_tbl") != 0
++        || result->objects.objects_val->EN_data.en_cols.en_cols_len < 4)
++      snprintf (buf, sizeof (buf), "[cname=%s,proto=%s],%s", name, protocol,
++                tablename_val);
++      else
+       {
+-        /* If we do not find it, try it as original name. But if the
+-           database is correct, we should find it in the first case, too */
+-        if ((result->status != NIS_SUCCESS
+-             && result->status != NIS_S_SUCCESS)
+-            || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
+-            || strcmp (result->objects.objects_val->EN_data.en_type,
+-                       "services_tbl") != 0
+-            || result->objects.objects_val->EN_data.en_cols.en_cols_len < 4)
+-          sprintf (buf, "[cname=%s,proto=%s],%s", name, protocol,
+-                   tablename_val);
+-        else
+-          sprintf (buf, "[cname=%s,proto=%s],%s",
+-                   NISENTRYVAL (0, 0, result), protocol, tablename_val);
+-
+-        nis_freeresult (result);
+-        result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++        /* We need to allocate a new buffer since there is no
++           guarantee the returned name has a length limit.  */
++        const char *entryval = NISENTRYVAL(0, 0, result);
++        size_t buflen = (strlen (entryval) + protocol_len + 17
++                         + tablename_len);
++        bufptr = alloca (buflen);
++        snprintf (bufptr, buflen, "[cname=%s,proto=%s],%s",
++                  entryval, protocol, tablename_val);
+       }
+-      if (result == NULL)
+-      {
+-        *errnop = ENOMEM;
+-        return NSS_STATUS_TRYAGAIN;
+-      }
+-      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+-      {
+-        enum nss_status status = niserr2nss (result->status);
++      nis_freeresult (result);
++      result = nis_list (bufptr, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++    }
+-        __set_errno (olderr);
++  if (result == NULL)
++    {
++      *errnop = ENOMEM;
++      return NSS_STATUS_TRYAGAIN;
++    }
+-        nis_freeresult (result);
+-        return status;
+-      }
++  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
++    {
++      enum nss_status status = niserr2nss (result->status);
++
++      __set_errno (olderr);
+-      parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen,
+-                                            errnop);
+       nis_freeresult (result);
++      return status;
++    }
+-      if (parse_res < 1)
++  int parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen,
++                                            errnop);
++  nis_freeresult (result);
++
++  if (__builtin_expect (parse_res < 1, 0))
++    {
++      if (parse_res == -1)
+       {
+-        if (parse_res == -1)
+-          {
+-            *errnop = ERANGE;
+-            return NSS_STATUS_TRYAGAIN;
+-          }
+-        else
+-          {
+-            __set_errno (olderr);
+-            return NSS_STATUS_NOTFOUND;
+-          }
++        *errnop = ERANGE;
++        return NSS_STATUS_TRYAGAIN;
++      }
++      else
++      {
++        __set_errno (olderr);
++        return NSS_STATUS_NOTFOUND;
+       }
+-      return NSS_STATUS_SUCCESS;
+     }
++
++  return NSS_STATUS_SUCCESS;
+ }
+ enum nss_status
+@@ -368,8 +385,12 @@ _nss_nisplus_getservbyport_r (const int 
+ {
+   if (tablename_val == NULL)
+     {
++      __libc_lock_lock (lock);
++
+       enum nss_status status = _nss_create_tablename (errnop);
++      __libc_lock_unlock (lock);
++
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+     }
+@@ -379,50 +400,48 @@ _nss_nisplus_getservbyport_r (const int 
+       *errnop = EINVAL;
+       return NSS_STATUS_NOTFOUND;
+     }
+-  else
+-    {
+-      int parse_res;
+-      nis_result *result;
+-      char buf[60 + strlen (protocol) + tablename_len];
+-      int olderr = errno;
+-      sprintf (buf, "[port=%d,proto=%s],%s",
+-             number, protocol, tablename_val);
++  char buf[17 + 3 * sizeof (int) + strlen (protocol) + tablename_len];
++  int olderr = errno;
+-      result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++  snprintf (buf, sizeof (buf), "[port=%d,proto=%s],%s",
++          number, protocol, tablename_val);
+-      if (result == NULL)
+-      {
+-        *errnop = ENOMEM;
+-        return NSS_STATUS_TRYAGAIN;
+-      }
+-      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+-      {
+-        enum nss_status status = niserr2nss (result->status);
++  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+-        __set_errno (olderr);
++  if (result == NULL)
++    {
++      *errnop = ENOMEM;
++      return NSS_STATUS_TRYAGAIN;
++    }
+-        nis_freeresult (result);
+-        return status;
+-      }
++  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
++    {
++      enum nss_status status = niserr2nss (result->status);
++
++      __set_errno (olderr);
+-      parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen,
+-                                            errnop);
+       nis_freeresult (result);
++      return status;
++    }
++
++  int parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen,
++                                            errnop);
++  nis_freeresult (result);
+-      if (parse_res < 1)
++  if (__builtin_expect (parse_res < 1, 0))
++    {
++      if (parse_res == -1)
+       {
+-        if (parse_res == -1)
+-          {
+-            *errnop = ERANGE;
+-            return NSS_STATUS_TRYAGAIN;
+-          }
+-        else
+-          {
+-            __set_errno (olderr);
+-            return NSS_STATUS_NOTFOUND;
+-          }
++        *errnop = ERANGE;
++        return NSS_STATUS_TRYAGAIN;
++      }
++      else
++      {
++        __set_errno (olderr);
++        return NSS_STATUS_NOTFOUND;
+       }
+-      return NSS_STATUS_SUCCESS;
+     }
++
++  return NSS_STATUS_SUCCESS;
+ }
+--- libc/nis/nss_nisplus/nisplus-spwd.c        25 Sep 2003 19:44:20 -0000      1.17
++++ libc/nis/nss_nisplus/nisplus-spwd.c        3 Dec 2005 20:38:57 -0000       1.19
+@@ -30,29 +30,12 @@
+ __libc_lock_define_initialized (static, lock)
+ static nis_result *result;
+-static nis_name tablename_val;
+-static u_long tablename_len;
+-static enum nss_status
+-_nss_create_tablename (int *errnop)
+-{
+-  if (tablename_val == NULL)
+-    {
+-      char buf [40 + strlen (nis_local_directory ())];
+-      char *p;
++/* Defined in nisplus-pwd.c.  */
++extern nis_name pwd_tablename_val attribute_hidden;
++extern size_t pwd_tablename_len attribute_hidden;
++extern enum nss_status _nss_pwd_create_tablename (int *errnop);
+-      p = __stpcpy (buf, "passwd.org_dir.");
+-      p = __stpcpy (p, nis_local_directory ());
+-      tablename_val = __strdup (buf);
+-      if (tablename_val == NULL)
+-      {
+-        *errnop = errno;
+-        return NSS_STATUS_TRYAGAIN;
+-      }
+-      tablename_len = strlen (tablename_val);
+-    }
+-  return NSS_STATUS_SUCCESS;
+-}
+ enum nss_status
+ _nss_nisplus_setspent (int stayopen)
+@@ -62,12 +45,14 @@ _nss_nisplus_setspent (int stayopen)
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+-  if (tablename_val == NULL)
+-    status = _nss_create_tablename (&err);
++  if (pwd_tablename_val == NULL)
++    status = _nss_pwd_create_tablename (&err);
+   __libc_lock_unlock (lock);
+@@ -79,9 +64,11 @@ _nss_nisplus_endspent (void)
+ {
+   __libc_lock_lock (lock);
+-  if (result)
+-    nis_freeresult (result);
+-  result = NULL;
++  if (result != NULL)
++    {
++      nis_freeresult (result);
++      result = NULL;
++    }
+   __libc_lock_unlock (lock);
+@@ -103,25 +90,22 @@ internal_nisplus_getspent_r (struct spwd
+       {
+         saved_res = NULL;
+-          if (tablename_val == NULL)
++          if (pwd_tablename_val == NULL)
+           {
+-            enum nss_status status = _nss_create_tablename (errnop);
++            enum nss_status status = _nss_pwd_create_tablename (errnop);
+             if (status != NSS_STATUS_SUCCESS)
+               return status;
+           }
+-        result = nis_first_entry (tablename_val);
++        result = nis_first_entry (pwd_tablename_val);
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           return niserr2nss (result->status);
+       }
+       else
+       {
+-        nis_result *res;
+-
+         saved_res = result;
+-        res = nis_next_entry (tablename_val, &result->cookie);
+-        result = res;
++        result = nis_next_entry (pwd_tablename_val, &result->cookie);
+         if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+           {
+             nis_freeresult (saved_res);
+@@ -131,19 +115,18 @@ internal_nisplus_getspent_r (struct spwd
+       parse_res = _nss_nisplus_parse_spent (result, sp, buffer,
+                                           buflen, errnop);
+-      if (parse_res == -1)
++      if (__builtin_expect (parse_res == -1, 0))
+       {
+         nis_freeresult (result);
+         result = saved_res;
+         *errnop = ERANGE;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      else
+-      {
+-        if (saved_res)
+-          nis_freeresult (saved_res);
+-      }
+-    } while (!parse_res);
++
++      if (saved_res != NULL)
++      nis_freeresult (saved_res);
++    }
++  while (!parse_res);
+   return NSS_STATUS_SUCCESS;
+ }
+@@ -169,9 +152,9 @@ _nss_nisplus_getspnam_r (const char *nam
+ {
+   int parse_res;
+-  if (tablename_val == NULL)
++  if (pwd_tablename_val == NULL)
+     {
+-      enum nss_status status = _nss_create_tablename (errnop);
++      enum nss_status status = _nss_pwd_create_tablename (errnop);
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+@@ -182,48 +165,47 @@ _nss_nisplus_getspnam_r (const char *nam
+       *errnop = EINVAL;
+       return NSS_STATUS_NOTFOUND;
+     }
+-  else
+-    {
+-      nis_result *result;
+-      char buf[strlen (name) + 24 + tablename_len];
+-      int olderr = errno;
+-      sprintf (buf, "[name=%s],%s", name, tablename_val);
++  nis_result *result;
++  char buf[strlen (name) + 9 + pwd_tablename_len];
++  int olderr = errno;
+-      result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++  snprintf (buf, sizeof (buf), "[name=%s],%s", name, pwd_tablename_val);
+-      if (result == NULL)
+-      {
+-        *errnop = ENOMEM;
+-        return NSS_STATUS_TRYAGAIN;
+-      }
+-      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+-      {
+-        enum nss_status status = niserr2nss (result->status);
++  result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+-        __set_errno (olderr);
++  if (result == NULL)
++    {
++      *errnop = ENOMEM;
++      return NSS_STATUS_TRYAGAIN;
++    }
+-        nis_freeresult (result);
+-        return status;
+-      }
++  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
++    {
++      enum nss_status status = niserr2nss (result->status);
++
++      __set_errno (olderr);
+-      parse_res = _nss_nisplus_parse_spent (result, sp, buffer, buflen,
+-                                          errnop);
+       nis_freeresult (result);
++      return status;
++    }
+-      if (parse_res < 1)
++  parse_res = _nss_nisplus_parse_spent (result, sp, buffer, buflen, errnop);
++  nis_freeresult (result);
++
++  if (__builtin_expect (parse_res < 1, 0))
++    {
++      if (parse_res == -1)
+       {
+-        if (parse_res == -1)
+-          {
+-            *errnop = ERANGE;
+-            return NSS_STATUS_TRYAGAIN;
+-          }
+-        else
+-          {
+-            __set_errno (olderr);
+-            return NSS_STATUS_NOTFOUND;
+-          }
++        *errnop = ERANGE;
++        return NSS_STATUS_TRYAGAIN;
++      }
++      else
++      {
++        __set_errno (olderr);
++        return NSS_STATUS_NOTFOUND;
+       }
+-      return NSS_STATUS_SUCCESS;
+     }
++
++  return NSS_STATUS_SUCCESS;
+ }
+--- libc/sunrpc/auth_des.c     17 Feb 2005 01:16:50 -0000      1.11
++++ libc/sunrpc/auth_des.c     7 Dec 2005 04:10:51 -0000       1.12
+@@ -174,7 +174,7 @@ authdes_pk_create (const char *servernam
+       if (key_gendes (&auth->ah_key) < 0)
+       {
+         debug ("authdes_create: unable to gen conversation key");
+-        return NULL;
++        goto failed;
+       }
+     }
+   else
diff --git a/src/patches/glibc/glibc-nis-getservbyname.patch b/src/patches/glibc/glibc-nis-getservbyname.patch
new file mode 100644 (file)
index 0000000..934d2d6
--- /dev/null
@@ -0,0 +1,16 @@
+2007-01-13  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nss_nis/nis-service.c (_nss_nis_getservbyname_r): Correct
+       computation of keylen.
+
+--- libc/nis/nss_nis/nis-service.c     19 Aug 2006 18:36:25 -0000      1.36
++++ libc/nis/nss_nis/nis-service.c     14 Jan 2007 04:30:39 -0000      1.37
+@@ -271,7 +271,7 @@ _nss_nis_getservbyname_r (const char *na
+   /* If the protocol is given, we could try if our NIS server knows
+      about services.byservicename map. If yes, we only need one query.  */
+-  size_t keylen = strlen (name) + 1 + (protocol ? strlen (protocol) : 0);
++  size_t keylen = strlen (name) + (protocol ? 1 + strlen (protocol) : 0);
+   char key[keylen + 1];
+   /* key is: "name/proto" */
diff --git a/src/patches/glibc/glibc-nis-publickey.patch b/src/patches/glibc/glibc-nis-publickey.patch
new file mode 100644 (file)
index 0000000..fa46577
--- /dev/null
@@ -0,0 +1,16 @@
+2005-10-28  Thorsten Kukuk  <kukuk@suse.de>
+
+       * nis/nss_nis/nis-publickey.c (_nss_nis_getpublickey): Fix off
+       by one error.
+
+--- libc/nis/nss_nis/nis-publickey.c   26 Aug 2002 06:20:04 -0000      1.13
++++ libc/nis/nss_nis/nis-publickey.c   28 Oct 2005 22:38:59 -0000      1.14
+@@ -120,7 +120,7 @@ _nss_nis_getsecretkey (const char *netna
+       ++p;
+       strncpy (buf, p, 2 * (HEXKEYBYTES + 1));
+-      buf[2 * (HEXKEYBYTES + 1)] = '\0';
++      buf[2 * HEXKEYBYTES + 1] = '\0';
+       if (!xdecrypt (buf, passwd))
+       return NSS_STATUS_SUCCESS;
diff --git a/src/patches/glibc/glibc-nis_leaf_of_r-0.patch b/src/patches/glibc/glibc-nis_leaf_of_r-0.patch
new file mode 100644 (file)
index 0000000..db6080f
--- /dev/null
@@ -0,0 +1,15 @@
+2005-08-15  Jakub Jelinek  <jakub@redhat.com>
+
+       * nis/nis_subr.c (nis_leaf_of_r): Handle buflen == 0 correctly.
+
+--- libc/nis/nis_subr.c        30 Jul 2005 19:36:23 -0000      1.13
++++ libc/nis/nis_subr.c        16 Aug 2005 15:59:46 -0000      1.14
+@@ -39,7 +39,7 @@ nis_leaf_of_r (const_nis_name name, char
+   while (name[i] != '.' && name[i] != '\0')
+     i++;
+-  if (i > buflen - 1)
++  if (i >= buflen)
+     {
+       __set_errno (ERANGE);
+       return NULL;
diff --git a/src/patches/glibc/glibc-nonnull.patch b/src/patches/glibc/glibc-nonnull.patch
new file mode 100644 (file)
index 0000000..66fa50c
--- /dev/null
@@ -0,0 +1,20 @@
+2007-05-10  Ulrich Drepper  <drepper@redhat.com>
+
+       * include/sys/cdefs.h: Redefine __nonnull so that test for
+       incorrect parameters in the libc code itself are not omitted.
+
+--- libc/include/sys/cdefs.h   18 Oct 2004 04:17:15 -0000      1.2
++++ libc/include/sys/cdefs.h   10 May 2007 20:15:11 -0000      1.3
+@@ -2,6 +2,12 @@
+ #include <misc/sys/cdefs.h>
++/* The compiler will optimize based on the knowledge the parameter is
++   not NULL.  This will omit tests.  A robust implementation cannot allow
++   this so when compiling glibc itself we ignore this attribute.  */
++#undef __nonnull
++#define __nonnull(params)
++
+ extern void __chk_fail (void) __attribute__ ((__noreturn__));
+ libc_hidden_proto (__chk_fail)
+ rtld_hidden_proto (__chk_fail)
diff --git a/src/patches/glibc/glibc-nptl-cancel-init.patch b/src/patches/glibc/glibc-nptl-cancel-init.patch
new file mode 100644 (file)
index 0000000..ea490ef
--- /dev/null
@@ -0,0 +1,18 @@
+2005-11-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/pthread/unwind-forcedunwind.c (pthread_cancel_init): Put
+       a write barrier before writing libgcc_s_getcfa.
+
+--- libc/nptl/sysdeps/pthread/unwind-forcedunwind.c    4 Sep 2003 05:41:57 -0000       1.1
++++ libc/nptl/sysdeps/pthread/unwind-forcedunwind.c    16 Nov 2005 23:31:28 -0000      1.2
+@@ -56,6 +56,10 @@ pthread_cancel_init (void)
+   libgcc_s_resume = resume;
+   libgcc_s_personality = personality;
+   libgcc_s_forcedunwind = forcedunwind;
++  /* Make sure libgcc_s_getcfa is written last.  Otherwise,
++     pthread_cancel_init might return early even when the pointer the
++     caller is interested in is not initialized yet.  */
++  atomic_write_barrier ();
+   libgcc_s_getcfa = getcfa;
+ }
diff --git a/src/patches/glibc/glibc-nptl-check.patch b/src/patches/glibc/glibc-nptl-check.patch
new file mode 100644 (file)
index 0000000..48951ea
--- /dev/null
@@ -0,0 +1,48 @@
+--- libc/sysdeps/unix/sysv/linux/dl-osinfo.h.jj        2002-12-10 09:09:24.000000000 -0500
++++ libc/sysdeps/unix/sysv/linux/dl-osinfo.h   2003-05-20 17:05:37.000000000 -0400
+@@ -22,6 +22,7 @@
+ #include <sys/sysctl.h>
+ #include <sys/utsname.h>
+ #include "kernel-features.h"
++#include <sysdep.h>
+ #ifndef MIN
+ # define MIN(a,b) (((a)<(b))?(a):(b))
+@@ -37,8 +38,29 @@ dl_fatal (const char *str)
+   _dl_dprintf (2, str);
+   _exit (1);
+ }
+-#endif
++static inline void
++__attribute__ ((always_inline))
++dl_redhat_nptl_check (const char *cp)
++{
++  cp = strchr (cp, 'n');
++  if (__builtin_expect (cp == NULL || cp[1] != 'p'
++                      || cp[2] != 't' || cp[3] != 'l', 0)
++      && GLRO(dl_osversion) < 0x20545
++      && GLRO(dl_osversion) > 0x20413)
++    {
++#ifdef __NR_set_tid_address
++      INTERNAL_SYSCALL_DECL (err);
++      int ret;
++      ret = INTERNAL_SYSCALL (set_tid_address, err, 1, NULL);
++      if (INTERNAL_SYSCALL_ERROR_P (ret, err))
++#endif
++      GLRO(dl_osversion) = 0x20413;
++    }
++}
++#else
++#define dl_redhat_nptl_check(cp)
++#endif
+ #define DL_SYSDEP_OSCHECK(FATAL) \
+   do {                                                                              \
+@@ -105,5 +127,6 @@ dl_fatal (const char *str)
+         FATAL ("FATAL: kernel too old\n");                                  \
+                                                                             \
+       GLRO(dl_osversion) = version;                                         \
++      dl_redhat_nptl_check (cp);                                            \
+       }                                                                             \
+   } while (0)
diff --git a/src/patches/glibc/glibc-nptl-fork-cancel.patch b/src/patches/glibc/glibc-nptl-fork-cancel.patch
new file mode 100644 (file)
index 0000000..389d449
--- /dev/null
@@ -0,0 +1,57 @@
+2006-04-08  Ulrich Drepper  <drepper@redhat.com>
+
+       * init.c (sigcancel_handler): Compare with correct PID even if the
+       thread is in the middle of a fork call.
+       (sighandler_setxid): Likewise.
+       Reported by Suzuki K P <suzuki@in.ibm.com> .
+
+--- libc/nptl/init.c   28 Mar 2006 04:15:08 -0000      1.57
++++ libc/nptl/init.c   8 Apr 2006 20:26:31 -0000       1.58
+@@ -148,6 +148,14 @@ static const struct pthread_functions pt
+ static void
+ sigcancel_handler (int sig, siginfo_t *si, void *ctx)
+ {
++#ifdef __ASSUME_CORRECT_SI_PID
++  /* Determine the process ID.  It might be negative if the thread is
++     in the middle of a fork() call.  */
++  pid_t pid = THREAD_GETMEM (THREAD_SELF, pid);
++  if (__builtin_expect (pid < 0, 0))
++    pid = -pid;
++#endif
++
+   /* Safety check.  It would be possible to call this function for
+      other signals and send a signal from another process.  This is not
+      correct and might even be a security problem.  Try to catch as
+@@ -156,7 +164,7 @@ sigcancel_handler (int sig, siginfo_t *s
+ #ifdef __ASSUME_CORRECT_SI_PID
+       /* Kernels before 2.5.75 stored the thread ID and not the process
+        ID in si_pid so we skip this test.  */
+-      || si->si_pid != THREAD_GETMEM (THREAD_SELF, pid)
++      || si->si_pid != pid
+ #endif
+       || si->si_code != SI_TKILL)
+     return;
+@@ -201,6 +209,14 @@ struct xid_command *__xidcmd attribute_h
+ static void
+ sighandler_setxid (int sig, siginfo_t *si, void *ctx)
+ {
++#ifdef __ASSUME_CORRECT_SI_PID
++  /* Determine the process ID.  It might be negative if the thread is
++     in the middle of a fork() call.  */
++  pid_t pid = THREAD_GETMEM (THREAD_SELF, pid);
++  if (__builtin_expect (pid < 0, 0))
++    pid = -pid;
++#endif
++
+   /* Safety check.  It would be possible to call this function for
+      other signals and send a signal from another process.  This is not
+      correct and might even be a security problem.  Try to catch as
+@@ -209,7 +225,7 @@ sighandler_setxid (int sig, siginfo_t *s
+ #ifdef __ASSUME_CORRECT_SI_PID
+       /* Kernels before 2.5.75 stored the thread ID and not the process
+        ID in si_pid so we skip this test.  */
+-      || si->si_pid != THREAD_GETMEM (THREAD_SELF, pid)
++      || si->si_pid != pid
+ #endif
+       || si->si_code != SI_TKILL)
+     return;
diff --git a/src/patches/glibc/glibc-nptl-fork-getpid.patch b/src/patches/glibc/glibc-nptl-fork-getpid.patch
new file mode 100644 (file)
index 0000000..000624c
--- /dev/null
@@ -0,0 +1,150 @@
+2006-07-31  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * allocatestack.c (__reclaim_stacks): Reset the PID on cached stacks.
+       * Makefile (tests): Add tst-getpid3.
+       * tst-getpid3.c: New file.
+
+--- libc/nptl/Makefile 31 Jul 2006 05:58:25 -0000      1.182
++++ libc/nptl/Makefile 1 Aug 2006 06:05:02 -0000       1.183
+@@ -256,7 +256,7 @@ tests = tst-typesizes \
+       tst-backtrace1 \
+       tst-oddstacklimit \
+       tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x \
+-      tst-getpid1 tst-getpid2 \
++      tst-getpid1 tst-getpid2 tst-getpid3 \
+       tst-initializers1 $(patsubst %,tst-initializers1-%,c89 gnu89 c99 gnu99)
+ xtests = tst-setuid1 tst-setuid1-static
+--- libc/nptl/allocatestack.c  28 Mar 2006 04:14:00 -0000      1.62
++++ libc/nptl/allocatestack.c  1 Aug 2006 06:04:42 -0000       1.63
+@@ -758,6 +756,13 @@ __reclaim_stacks (void)
+       }
+     }
++  /* Reset the PIDs in any cached stacks.  */
++  list_for_each (runp, &stack_cache)
++    {
++      struct pthread *curp = list_entry (runp, struct pthread, list);
++      curp->pid = self->pid;
++    }
++
+   /* Add the stack of all running threads to the cache.  */
+   list_splice (&stack_used, &stack_cache);
+--- libc/nptl/tst-getpid3.c    1 Jan 1970 00:00:00 -0000
++++ libc/nptl/tst-getpid3.c    1 Aug 2006 06:04:02 -0000       1.1
+@@ -0,0 +1,114 @@
++#include <errno.h>
++#include <pthread.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/wait.h>
++
++
++static pid_t pid;
++
++static void *
++pid_thread (void *arg)
++{
++  if (pid != getpid ())
++    {
++      printf ("pid wrong in thread: should be %d, is %d\n",
++            (int) pid, (int) getpid ());
++      return (void *) 1L;
++    }
++
++  return NULL;
++}
++
++static int
++do_test (void)
++{
++  pid = getpid ();
++
++  pthread_t thr;
++  int ret = pthread_create (&thr, NULL, pid_thread, NULL);
++  if (ret)
++    {
++      printf ("pthread_create failed: %d\n", ret);
++      return 1;
++    }
++
++  void *thr_ret;
++  ret = pthread_join (thr, &thr_ret);
++  if (ret)
++    {
++      printf ("pthread_create failed: %d\n", ret);
++      return 1;
++    }
++  else if (thr_ret)
++    {
++      printf ("thread getpid failed\n");
++      return 1;
++    }
++
++  pid_t child = fork ();
++  if (child == -1)
++    {
++      printf ("fork failed: %m\n");
++      return 1;
++    }
++  else if (child == 0)
++    {
++      if (pid == getpid ())
++      {
++        puts ("pid did not change after fork");
++        exit (1);
++      }
++
++      pid = getpid ();
++      ret = pthread_create (&thr, NULL, pid_thread, NULL);
++      if (ret)
++      {
++        printf ("pthread_create failed: %d\n", ret);
++        return 1;
++      }
++
++      ret = pthread_join (thr, &thr_ret);
++      if (ret)
++      {
++        printf ("pthread_create failed: %d\n", ret);
++        return 1;
++      }
++      else if (thr_ret)
++      {
++        printf ("thread getpid failed\n");
++        return 1;
++      }
++
++      return 0;
++    }
++
++  int status;
++  if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
++    {
++      puts ("waitpid failed");
++      kill (child, SIGKILL);
++      return 1;
++    }
++
++  if (!WIFEXITED (status))
++    {
++      if (WIFSIGNALED (status))
++      printf ("died from signal %s\n", strsignal (WTERMSIG (status)));
++      else
++      puts ("did not terminate correctly");
++      return 1;
++    }
++  if (WEXITSTATUS (status) != 0)
++    {
++      printf ("exit code %d\n", WEXITSTATUS (status));
++      return 1;
++    }
++
++  return 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-nptl-futex-wait.patch b/src/patches/glibc/glibc-nptl-futex-wait.patch
new file mode 100644 (file)
index 0000000..2a1a7bf
--- /dev/null
@@ -0,0 +1,27 @@
+2006-02-08  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_futex_wait,
+       lll_wait_tid): Add "memory" clobber.
+
+--- libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h.jj   2004-03-24 01:35:18.000000000 -0500
++++ libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h      2004-03-24 01:35:18.000000000 -0500
+@@ -75,7 +75,8 @@
+                     : "=a" (__ignore)                                       \
+                     : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (0),        \
+                       "c" (FUTEX_WAIT), "d" (_val),                         \
+-                      "i" (offsetof (tcbhead_t, sysinfo)));                 \
++                      "i" (offsetof (tcbhead_t, sysinfo))                   \
++                    : "memory");                                            \
+   } while (0)
+@@ -330,7 +331,8 @@ extern int lll_unlock_wake_cb (int *__fu
+                       : "=&a" (__ignore)                                    \
+                       : "i" (SYS_futex), LLL_EBX_REG (&tid), "S" (0),       \
+                         "c" (FUTEX_WAIT), "d" (_tid),                       \
+-                        "i" (offsetof (tcbhead_t, sysinfo)));               \
++                        "i" (offsetof (tcbhead_t, sysinfo))                 \
++                      : "memory");                                          \
+   } while (0)
+ extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime)
diff --git a/src/patches/glibc/glibc-nptl-setxid-2.patch b/src/patches/glibc/glibc-nptl-setxid-2.patch
new file mode 100644 (file)
index 0000000..23fe2cf
--- /dev/null
@@ -0,0 +1,213 @@
+2006-09-27  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       [BZ #3270]
+       * allocatestack.c (setxid_mark_thread, setxid_unmark_thread): New.
+       (setxid_signal_thread): Return a successful signal indicator.  Just
+       skip threads without SETXID_BITMASK.
+       (__nptl_setxid): Perform the operation in multiple
+       steps to avoid races with creation and terminations.
+       * init.c (sighandler_setxid): Adjust.
+
+diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
+index 67ea0c6..3c3585f 100644
+--- a/nptl/allocatestack.c
++++ b/nptl/allocatestack.c
+@@ -965,22 +965,53 @@ __find_thread_by_id (pid_t tid)
+ static void
+ internal_function
+-setxid_signal_thread (struct xid_command *cmdp, struct pthread *t)
++setxid_mark_thread (struct xid_command *cmdp, struct pthread *t)
+ {
+-  if (! IS_DETACHED (t))
++  int ch;
++
++  /* Don't let the thread exit before the setxid handler runs.  */
++  t->setxid_futex = 0;
++
++  do
+     {
+-      int ch;
+-      do
+-      {
+-        ch = t->cancelhandling;
++      ch = t->cancelhandling;
+-        /* If the thread is exiting right now, ignore it.  */
+-        if ((ch & EXITING_BITMASK) != 0)
+-          return;
+-      }
+-      while (atomic_compare_and_exchange_bool_acq (&t->cancelhandling,
+-                                                 ch | SETXID_BITMASK, ch));
++      /* If the thread is exiting right now, ignore it.  */
++      if ((ch & EXITING_BITMASK) != 0)
++      return;
+     }
++  while (atomic_compare_and_exchange_bool_acq (&t->cancelhandling,
++                                             ch | SETXID_BITMASK, ch));
++}
++
++
++static void
++internal_function
++setxid_unmark_thread (struct xid_command *cmdp, struct pthread *t)
++{
++  int ch;
++
++  do
++    {
++      ch = t->cancelhandling;
++      if ((ch & SETXID_BITMASK) == 0)
++      return;
++    }
++  while (atomic_compare_and_exchange_bool_acq (&t->cancelhandling,
++                                             ch & ~SETXID_BITMASK, ch));
++
++  /* Release the futex just in case.  */
++  t->setxid_futex = 1;
++  lll_futex_wake (&t->setxid_futex, 1);
++}
++
++
++static int
++internal_function
++setxid_signal_thread (struct xid_command *cmdp, struct pthread *t)
++{
++  if ((t->cancelhandling & SETXID_BITMASK) == 0)
++    return 0;
+   int val;
+   INTERNAL_SYSCALL_DECL (err);
+@@ -997,8 +1028,14 @@ setxid_signal_thread (struct xid_command *cmdp, struct pthread *t)
+     val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID);
+ #endif
++  /* If this failed, it must have had not started yet or else exited.  */
+   if (!INTERNAL_SYSCALL_ERROR_P (val, err))
+-    atomic_increment (&cmdp->cntr);
++    {
++      atomic_increment (&cmdp->cntr);
++      return 1;
++    }
++  else
++    return 0;
+ }
+@@ -1006,6 +1043,7 @@ int
+ attribute_hidden
+ __nptl_setxid (struct xid_command *cmdp)
+ {
++  int signalled;
+   int result;
+   lll_lock (stack_cache_lock);
+@@ -1022,7 +1060,7 @@ __nptl_setxid (struct xid_command *cmdp)
+       if (t == self)
+       continue;
+-      setxid_signal_thread (cmdp, t);
++      setxid_mark_thread (cmdp, t);
+     }
+   /* Now the list with threads using user-allocated stacks.  */
+@@ -1032,14 +1070,61 @@ __nptl_setxid (struct xid_command *cmdp)
+       if (t == self)
+       continue;
+-      setxid_signal_thread (cmdp, t);
++      setxid_mark_thread (cmdp, t);
+     }
+-  int cur = cmdp->cntr;
+-  while (cur != 0)
++  /* Iterate until we don't succeed in signalling anyone.  That means
++     we have gotten all running threads, and their children will be
++     automatically correct once started.  */
++  do
+     {
+-      lll_futex_wait (&cmdp->cntr, cur);
+-      cur = cmdp->cntr;
++      signalled = 0;
++
++      list_for_each (runp, &stack_used)
++      {
++        struct pthread *t = list_entry (runp, struct pthread, list);
++        if (t == self)
++          continue;
++
++        signalled += setxid_signal_thread (cmdp, t);
++      }
++
++      list_for_each (runp, &__stack_user)
++      {
++        struct pthread *t = list_entry (runp, struct pthread, list);
++        if (t == self)
++          continue;
++
++        signalled += setxid_signal_thread (cmdp, t);
++      }
++
++      int cur = cmdp->cntr;
++      while (cur != 0)
++      {
++        lll_futex_wait (&cmdp->cntr, cur);
++        cur = cmdp->cntr;
++      }
++    }
++  while (signalled != 0);
++
++  /* Clean up flags, so that no thread blocks during exit waiting
++     for a signal which will never come.  */
++  list_for_each (runp, &stack_used)
++    {
++      struct pthread *t = list_entry (runp, struct pthread, list);
++      if (t == self)
++      continue;
++
++      setxid_unmark_thread (cmdp, t);
++    }
++
++  list_for_each (runp, &__stack_user)
++    {
++      struct pthread *t = list_entry (runp, struct pthread, list);
++      if (t == self)
++      continue;
++
++      setxid_unmark_thread (cmdp, t);
+     }
+   /* This must be last, otherwise the current thread might not have
+diff --git a/nptl/init.c b/nptl/init.c
+index 5e9c250..851bab2 100644
+--- a/nptl/init.c
++++ b/nptl/init.c
+@@ -240,17 +240,23 @@ sighandler_setxid (int sig, siginfo_t *si, void *ctx)
+   INTERNAL_SYSCALL_NCS (__xidcmd->syscall_no, err, 3, __xidcmd->id[0],
+                       __xidcmd->id[1], __xidcmd->id[2]);
+-  if (atomic_decrement_val (&__xidcmd->cntr) == 0)
+-    lll_futex_wake (&__xidcmd->cntr, 1);
+-
+   /* Reset the SETXID flag.  */
+   struct pthread *self = THREAD_SELF;
+-  int flags = THREAD_GETMEM (self, cancelhandling);
+-  THREAD_SETMEM (self, cancelhandling, flags & ~SETXID_BITMASK);
++  int flags, newval;
++  do
++    {
++      flags = THREAD_GETMEM (self, cancelhandling);
++      newval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
++                                        flags & ~SETXID_BITMASK, flags);
++    }
++  while (flags != newval);
+   /* And release the futex.  */
+   self->setxid_futex = 1;
+   lll_futex_wake (&self->setxid_futex, 1);
++
++  if (atomic_decrement_val (&__xidcmd->cntr) == 0)
++    lll_futex_wake (&__xidcmd->cntr, 1);
+ }
diff --git a/src/patches/glibc/glibc-nptl-setxid.patch b/src/patches/glibc/glibc-nptl-setxid.patch
new file mode 100644 (file)
index 0000000..61f383b
--- /dev/null
@@ -0,0 +1,263 @@
+2005-10-03  Jakub Jelinek  <jakub@redhat.com>
+
+       * allocatestack.c (setxid_signal_thread): Add
+       INTERNAL_SYSCALL_DECL (err).
+
+2005-10-02  Jakub Jelinek  <jakub@redhat.com>
+
+       * allocatestack.c (setxid_signal_thread): Need to use
+       atomic_compare_and_exchange_bool_acq.
+
+2005-10-01  Ulrich Drepper  <drepper@redhat.com>
+            Jakub Jelinek  <jakub@redhat.com>
+
+       * descr.h: Define SETXID_BIT and SETXID_BITMASK.  Adjust
+       CANCEL_RESTMASK.
+       (struct pthread): Move specific_used field to avoid padding.
+       Add setxid_futex field.
+       * init.c (sighandler_setxid): Reset setxid flag and release the
+       setxid futex.
+       * allocatestack.c (setxid_signal_thread): New function.  Broken
+       out of the bodies of the two loops in __nptl_setxid.  For undetached
+       threads check whether they are exiting and if yes, don't send a signal.
+       (__nptl_setxid): Simplify loops by using setxid_signal_thread.
+       * pthread_create.c (start_thread): For undetached threads, check
+       whether setxid bit is set.  If yes, wait until signal has been
+       processed.
+
+       * allocatestack.c (STACK_VARIABLES): Initialize them.
+       * pthread_create.c (__pthread_create_2_1): Initialize pd.
+
+--- libc/nptl/pthread_create.c 26 Jun 2005 17:45:44 -0000      1.43
++++ libc/nptl/pthread_create.c 1 Oct 2005 17:19:37 -0000       1.44
+@@ -314,6 +314,17 @@ start_thread (void *arg)
+   if (IS_DETACHED (pd))
+     /* Free the TCB.  */
+     __free_tcb (pd);
++  else if (__builtin_expect (pd->cancelhandling & SETXID_BITMASK, 0))
++    {
++      /* Some other thread might call any of the setXid functions and expect
++       us to reply.  In this case wait until we did that.  */
++      do
++      lll_futex_wait (&pd->setxid_futex, 0);
++      while (pd->cancelhandling & SETXID_BITMASK);
++
++      /* Reset the value so that the stack can be reused.  */
++      pd->setxid_futex = 0;
++    }
+   /* We cannot call '_exit' here.  '_exit' will terminate the process.
+@@ -348,7 +359,7 @@ __pthread_create_2_1 (newthread, attr, s
+ {
+   STACK_VARIABLES;
+   const struct pthread_attr *iattr;
+-  struct pthread *pd;
++  struct pthread *pd = NULL;
+   int err;
+   iattr = (struct pthread_attr *) attr;
+--- libc/nptl/descr.h  7 Jul 2005 06:07:13 -0000       1.26
++++ libc/nptl/descr.h  1 Oct 2005 17:19:00 -0000       1.27
+@@ -161,8 +161,11 @@ struct pthread
+   /* Bit set if thread terminated and TCB is freed.  */
+ #define TERMINATED_BIT                5
+ #define TERMINATED_BITMASK    0x20
++  /* Bit set if thread is supposed to change XID.  */
++#define SETXID_BIT            6
++#define SETXID_BITMASK                0x40
+   /* Mask for the rest.  Helps the compiler to optimize.  */
+-#define CANCEL_RESTMASK               0xffffffc0
++#define CANCEL_RESTMASK               0xffffff80
+ #define CANCEL_ENABLED_AND_CANCELED(value) \
+   (((value) & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK             \
+@@ -185,12 +188,12 @@ struct pthread
+     void *data;
+   } specific_1stblock[PTHREAD_KEY_2NDLEVEL_SIZE];
+-  /* Flag which is set when specific data is set.  */
+-  bool specific_used;
+-
+   /* Two-level array for the thread-specific data.  */
+   struct pthread_key_data *specific[PTHREAD_KEY_1STLEVEL_SIZE];
++  /* Flag which is set when specific data is set.  */
++  bool specific_used;
++
+   /* True if events must be reported.  */
+   bool report_events;
+@@ -203,6 +206,9 @@ struct pthread
+   /* Lock to synchronize access to the descriptor.  */
+   lll_lock_t lock;
++  /* Lock for synchronizing setxid calls.  */
++  lll_lock_t setxid_futex;
++
+ #if HP_TIMING_AVAIL
+   /* Offset of the CPU clock at start thread start time.  */
+   hp_timing_t cpuclock_offset;
+--- libc/nptl/init.c   28 Dec 2004 01:39:50 -0000      1.52
++++ libc/nptl/init.c   1 Oct 2005 17:18:11 -0000       1.53
+@@ -211,6 +211,15 @@ sighandler_setxid (int sig, siginfo_t *s
+   if (atomic_decrement_val (&__xidcmd->cntr) == 0)
+     lll_futex_wake (&__xidcmd->cntr, 1);
++
++  /* Reset the SETXID flag.  */
++  struct pthread *self = THREAD_SELF;
++  int flags = THREAD_GETMEM (self, cancelhandling);
++  THREAD_SETMEM (self, cancelhandling, flags & ~SETXID_BITMASK);
++
++  /* And release the futex.  */
++  self->setxid_futex = 1;
++  lll_futex_wake (&self->setxid_futex, 1);
+ }
+--- libc/nptl/allocatestack.c  6 Jan 2005 22:40:24 -0000       1.56
++++ libc/nptl/allocatestack.c  4 Oct 2005 00:40:01 -0000       1.59
+@@ -33,7 +34,7 @@
+ #ifndef NEED_SEPARATE_REGISTER_STACK
+ /* Most architectures have exactly one stack pointer.  Some have more.  */
+-# define STACK_VARIABLES void *stackaddr
++# define STACK_VARIABLES void *stackaddr = NULL
+ /* How to pass the values to the 'create_thread' function.  */
+ # define STACK_VARIABLES_ARGS stackaddr
+@@ -52,7 +53,7 @@
+ /* We need two stacks.  The kernel will place them but we have to tell
+    the kernel about the size of the reserved address space.  */
+-# define STACK_VARIABLES void *stackaddr; size_t stacksize
++# define STACK_VARIABLES void *stackaddr = NULL; size_t stacksize = 0
+ /* How to pass the values to the 'create_thread' function.  */
+ # define STACK_VARIABLES_ARGS stackaddr, stacksize
+@@ -817,6 +818,46 @@ __find_thread_by_id (pid_t tid)
+ }
+ #endif
++
++static void
++internal_function
++setxid_signal_thread (struct xid_command *cmdp, struct pthread *t)
++{
++  if (! IS_DETACHED (t))
++    {
++      int ch;
++      do
++      {
++        ch = t->cancelhandling;
++
++        /* If the thread is exiting right now, ignore it.  */
++        if ((ch & EXITING_BITMASK) != 0)
++          return;
++      }
++      while (atomic_compare_and_exchange_bool_acq (&t->cancelhandling,
++                                                 ch | SETXID_BITMASK, ch));
++    }
++
++  int val;
++  INTERNAL_SYSCALL_DECL (err);
++#if __ASSUME_TGKILL
++  val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
++                        t->tid, SIGSETXID);
++#else
++# ifdef __NR_tgkill
++  val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
++                        t->tid, SIGSETXID);
++  if (INTERNAL_SYSCALL_ERROR_P (val, err)
++      && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS)
++# endif
++    val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID);
++#endif
++
++  if (!INTERNAL_SYSCALL_ERROR_P (val, err))
++    atomic_increment (&cmdp->cntr);
++}
++
++
+ int
+ attribute_hidden
+ __nptl_setxid (struct xid_command *cmdp)
+@@ -827,8 +868,6 @@ __nptl_setxid (struct xid_command *cmdp)
+   __xidcmd = cmdp;
+   cmdp->cntr = 0;
+-  INTERNAL_SYSCALL_DECL (err);
+-
+   struct pthread *self = THREAD_SELF;
+   /* Iterate over the list with system-allocated threads first.  */
+@@ -836,54 +875,20 @@ __nptl_setxid (struct xid_command *cmdp)
+   list_for_each (runp, &stack_used)
+     {
+       struct pthread *t = list_entry (runp, struct pthread, list);
+-      if (t != self)
+-      {
+-        int val;
+-#if __ASSUME_TGKILL
+-        val = INTERNAL_SYSCALL (tgkill, err, 3,
+-                                THREAD_GETMEM (THREAD_SELF, pid),
+-                                t->tid, SIGSETXID);
+-#else
+-# ifdef __NR_tgkill
+-        val = INTERNAL_SYSCALL (tgkill, err, 3,
+-                                THREAD_GETMEM (THREAD_SELF, pid),
+-                                t->tid, SIGSETXID);
+-        if (INTERNAL_SYSCALL_ERROR_P (val, err)
+-            && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS)
+-# endif
+-          val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID);
+-#endif
++      if (t == self)
++      continue;
+-        if (!INTERNAL_SYSCALL_ERROR_P (val, err))
+-          atomic_increment (&cmdp->cntr);
+-      }
++      setxid_signal_thread (cmdp, t);
+     }
+   /* Now the list with threads using user-allocated stacks.  */
+   list_for_each (runp, &__stack_user)
+     {
+       struct pthread *t = list_entry (runp, struct pthread, list);
+-      if (t != self)
+-      {
+-        int val;
+-#if __ASSUME_TGKILL
+-        val = INTERNAL_SYSCALL (tgkill, err, 3,
+-                                THREAD_GETMEM (THREAD_SELF, pid),
+-                                t->tid, SIGSETXID);
+-#else
+-# ifdef __NR_tgkill
+-        val = INTERNAL_SYSCALL (tgkill, err, 3,
+-                                THREAD_GETMEM (THREAD_SELF, pid),
+-                                t->tid, SIGSETXID);
+-        if (INTERNAL_SYSCALL_ERROR_P (val, err)
+-            && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS)
+-# endif
+-          val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID);
+-#endif
++      if (t == self)
++      continue;
+-        if (!INTERNAL_SYSCALL_ERROR_P (val, err))
+-          atomic_increment (&cmdp->cntr);
+-      }
++      setxid_signal_thread (cmdp, t);
+     }
+   int cur = cmdp->cntr;
+@@ -895,6 +900,7 @@ __nptl_setxid (struct xid_command *cmdp)
+   /* This must be last, otherwise the current thread might not have
+      permissions to send SIGSETXID syscall to the other threads.  */
++  INTERNAL_SYSCALL_DECL (err);
+   result = INTERNAL_SYSCALL_NCS (cmdp->syscall_no, err, 3,
+                                cmdp->id[0], cmdp->id[1], cmdp->id[2]);
+   if (INTERNAL_SYSCALL_ERROR_P (result, err))
diff --git a/src/patches/glibc/glibc-nscd-EINTR.patch b/src/patches/glibc/glibc-nscd-EINTR.patch
new file mode 100644 (file)
index 0000000..eba2ced
--- /dev/null
@@ -0,0 +1,177 @@
+2005-08-23  Ulrich Drepper  <drepper@redhat.com>
+       * nscd/mem.c (mempool_alloc): Use posix_fallocate correctly.
+       * nscd/nscd.h: Temporarily define TEMP_FAILURE_RETRY_VAL here.
+
+       * nscd/aicache.c (addhstaiX): Use send with MSG_NOSIGNAL not write to
+       send reply.
+       * nscd/connections.c (writeall): Likewise.
+       (handle_request): Likewise.
+       * nscd/grpcache.c (cache_addgr): Likewise.
+       * nscd/hstcache.c (cache_addhst): Likewise.
+       * nscd/initgrcache.c (addinitgroupsX): Likewise.
+       * nscd/nscd.c (parse_opt): Likewise.
+       * nscd/nscd_stat.c (send_stats): Likewise.
+       (receive_print_stats): Likewise.
+       * nscd/pwdcache.c (cache_addpw): Likewise.
+
+--- libc/nscd/aicache.c        17 Mar 2005 09:43:42 -0000      1.7
++++ libc/nscd/aicache.c        23 Aug 2005 23:09:12 -0000      1.8
+@@ -399,7 +399,7 @@ addhstaiX (struct database_dyn *db, int 
+       total = sizeof (notfound);
+       if (fd != -1)
+-      TEMP_FAILURE_RETRY (write (fd, &notfound, total));
++      TEMP_FAILURE_RETRY (send (fd, &notfound, total, MSG_NOSIGNAL));
+       dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
+       /* If we cannot permanently store the result, so be it.  */
+--- libc/nscd/connections.c    16 Aug 2005 18:07:46 -0000      1.75
++++ libc/nscd/connections.c    23 Aug 2005 23:12:00 -0000      1.76
+@@ -188,7 +187,7 @@ writeall (int fd, const void *buf, size_
+   ssize_t ret;
+   do
+     {
+-      ret = TEMP_FAILURE_RETRY (write (fd, buf, n));
++      ret = TEMP_FAILURE_RETRY (send (fd, buf, n, MSG_NOSIGNAL));
+       if (ret <= 0)
+       break;
+       buf = (const char *) buf + ret;
+@@ -638,8 +645,9 @@ cannot create read-only descriptor for \
+               if ((TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head)))
+                    != sizeof (head))
+-                  || posix_fallocate (fd, 0, total) != 0
++                  || (TEMP_FAILURE_RETRY_VAL (posix_fallocate (fd, 0, total))
++                      != 0)
+                   || (mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
+                                   MAP_SHARED, fd, 0)) == MAP_FAILED)
+                 {
+                 write_fail:
+@@ -901,8 +910,9 @@ cannot handle old request version %d; cu
+       if (!db->enabled)
+       {
+         /* No, sent the prepared record.  */
+-        if (TEMP_FAILURE_RETRY (write (fd, db->disabled_iov->iov_base,
+-                                       db->disabled_iov->iov_len))
++        if (TEMP_FAILURE_RETRY (send (fd, db->disabled_iov->iov_base,
++                                      db->disabled_iov->iov_len,
++                                      MSG_NOSIGNAL))
+             != (ssize_t) db->disabled_iov->iov_len
+             && __builtin_expect (debug_level, 0) > 0)
+           {
+--- libc/nscd/grpcache.c       18 Jul 2005 21:05:40 -0000      1.39
++++ libc/nscd/grpcache.c       23 Aug 2005 23:12:43 -0000      1.40
+@@ -107,7 +107,8 @@ cache_addgr (struct database_dyn *db, in
+            case.  */
+         total = sizeof (notfound);
+-        written = TEMP_FAILURE_RETRY (write (fd, &notfound, total));
++        written = TEMP_FAILURE_RETRY (send (fd, &notfound, total,
++                                            MSG_NOSIGNAL));
+         dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
+         /* If we cannot permanently store the result, so be it.  */
+--- libc/nscd/hstcache.c       22 Feb 2005 22:53:39 -0000      1.33
++++ libc/nscd/hstcache.c       23 Aug 2005 23:13:14 -0000      1.34
+@@ -115,7 +115,8 @@ cache_addhst (struct database_dyn *db, i
+         written = total = sizeof (notfound);
+         if (fd != -1)
+-          written = TEMP_FAILURE_RETRY (write (fd, &notfound, total));
++          written = TEMP_FAILURE_RETRY (send (fd, &notfound, total,
++                                              MSG_NOSIGNAL));
+         dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
+         /* If we cannot permanently store the result, so be it.  */
+--- libc/nscd/initgrcache.c    22 Feb 2005 22:47:45 -0000      1.3
++++ libc/nscd/initgrcache.c    23 Aug 2005 23:14:05 -0000      1.4
+@@ -188,7 +188,8 @@ addinitgroupsX (struct database_dyn *db,
+         /* We have no data.  This means we send the standard reply for this
+            case.  */
+         if (fd != -1)
+-          written = TEMP_FAILURE_RETRY (write (fd, &notfound, total));
++          written = TEMP_FAILURE_RETRY (send (fd, &notfound, total,
++                                              MSG_NOSIGNAL));
+         dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
+         /* If we cannot permanently store the result, so be it.  */
+--- libc/nscd/mem.c    8 Aug 2005 20:38:42 -0000       1.6
++++ libc/nscd/mem.c    23 Aug 2005 23:15:28 -0000      1.7
+@@ -490,7 +490,10 @@ mempool_alloc (struct database_dyn *db, 
+                            + new_data_size);
+         if ((!db->mmap_used
+-             || posix_fallocate (db->wr_fd, oldtotal, newtotal) != 0)
++             || TEMP_FAILURE_RETRY_VAL (posix_fallocate (db->wr_fd,
++                                                         oldtotal,
++                                                         newtotal - oldtotal))
++                                        != 0)
+             /* Try to resize the mapping.  Note: no MREMAP_MAYMOVE.  */
+             && mremap (db->head, oldtotal, newtotal, 0) == 0)
+           {
+--- libc/nscd/nscd.c   19 Jul 2005 15:30:46 -0000      1.46
++++ libc/nscd/nscd.c   23 Aug 2005 23:16:20 -0000      1.47
+@@ -315,8 +315,9 @@ parse_opt (int key, char *arg, struct ar
+       req.version = NSCD_VERSION;
+       req.type = SHUTDOWN;
+       req.key_len = 0;
+-      nbytes = TEMP_FAILURE_RETRY (write (sock, &req,
+-                                          sizeof (request_header)));
++      nbytes = TEMP_FAILURE_RETRY (send (sock, &req,
++                                         sizeof (request_header),
++                                         MSG_NOSIGNAL));
+       close (sock);
+       exit (nbytes != sizeof (request_header) ? EXIT_FAILURE : EXIT_SUCCESS);
+       }
+--- libc/nscd/nscd.h   8 Aug 2005 18:54:44 -0000       1.22
++++ libc/nscd/nscd.h   23 Aug 2005 23:18:23 -0000      1.23
+@@ -241,4 +248,14 @@ extern void gc (struct database_dyn *db)
+ /* nscd_setup_thread.c */
+ extern void setup_thread (struct database_dyn *db);
++
++/* Special version of TEMP_FAILURE_RETRY for functions returning error
++   values.  */
++#define TEMP_FAILURE_RETRY_VAL(expression) \
++  (__extension__                                                            \
++    ({ long int __result;                                                   \
++       do __result = (long int) (expression);                               \
++       while (__result == EINTR);                                           \
++       __result; }))
++
+ #endif /* nscd.h */
+--- libc/nscd/nscd_stat.c      9 Aug 2005 05:45:03 -0000       1.15
++++ libc/nscd/nscd_stat.c      23 Aug 2005 23:20:21 -0000      1.16
+@@ -133,7 +133,8 @@ send_stats (int fd, struct database_dyn 
+   if (selinux_enabled)
+     nscd_avc_cache_stats (&data.cstats);
+-  if (TEMP_FAILURE_RETRY (write (fd, &data, sizeof (data))) != sizeof (data))
++  if (TEMP_FAILURE_RETRY (send (fd, &data, sizeof (data), MSG_NOSIGNAL))
++      != sizeof (data))
+     {
+       char buf[256];
+       dbg_log (_("cannot write statistics: %s"),
+@@ -180,7 +181,8 @@ receive_print_stats (void)
+   req.version = NSCD_VERSION;
+   req.type = GETSTAT;
+   req.key_len = 0;
+-  nbytes = TEMP_FAILURE_RETRY (write (fd, &req, sizeof (request_header)));
++  nbytes = TEMP_FAILURE_RETRY (send (fd, &req, sizeof (request_header),
++                                   MSG_NOSIGNAL));
+   if (nbytes != sizeof (request_header))
+     {
+       int err = errno;
+--- libc/nscd/pwdcache.c       22 Feb 2005 22:53:39 -0000      1.37
++++ libc/nscd/pwdcache.c       23 Aug 2005 23:21:02 -0000      1.38
+@@ -114,7 +114,8 @@ cache_addpw (struct database_dyn *db, in
+         written = total = sizeof (notfound);
+         if (fd != -1)
+-          written = TEMP_FAILURE_RETRY (write (fd, &notfound, total));
++          written = TEMP_FAILURE_RETRY (send (fd, &notfound, total,
++                                              MSG_NOSIGNAL));
+         dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
+         /* If we cannot permanently store the result, so be it.  */
diff --git a/src/patches/glibc/glibc-nscd-LFS-logging.patch b/src/patches/glibc/glibc-nscd-LFS-logging.patch
new file mode 100644 (file)
index 0000000..dd472c4
--- /dev/null
@@ -0,0 +1,15 @@
+2005-09-20  Jakub Jelinek  <jakub@redhat.com>
+
+       * nscd/dbg_log.c (init_logfile): Use fopen64 rather than fopen.
+
+--- libc/nscd/dbg_log.c        2 Oct 2004 21:38:53 -0000       1.7
++++ libc/nscd/dbg_log.c        20 Sep 2005 20:15:04 -0000      1.8
+@@ -44,7 +44,7 @@ init_logfile (void)
+ {
+   if (logfilename)
+     {
+-      dbgout = fopen (logfilename, "a");
++      dbgout = fopen64 (logfilename, "a");
+       return dbgout == NULL ? 0 : 1;
+     }
+   return 1;
diff --git a/src/patches/glibc/glibc-nscd-SIGHUP-disabled-cache.patch b/src/patches/glibc/glibc-nscd-SIGHUP-disabled-cache.patch
new file mode 100644 (file)
index 0000000..0a2d588
--- /dev/null
@@ -0,0 +1,27 @@
+2006-04-26  Jakub Jelinek  <jakub@redhat.com>
+
+       * nscd/connections.c (sighup_handler): Only run prune_cache on
+       enabled databases.
+
+--- libc/nscd/connections.c.jj 2006-04-26 09:03:38.000000000 -0400
++++ libc/nscd/connections.c    2006-04-26 09:04:35.000000000 -0400
+@@ -687,13 +687,16 @@ finish_drop_privileges (void)
+ void
+ sighup_handler (int signum)
+ {
+-    /* Prune the password database */
++  /* Prune the password database.  */
++  if (dbs[pwddb].enabled)
+     prune_cache (&dbs[pwddb], LONG_MAX);
+     
+-    /* Prune the group database */
++  /* Prune the group database.  */
++  if (dbs[grpdb].enabled)
+     prune_cache (&dbs[grpdb], LONG_MAX);
+-    /* Prune the host database */
++  /* Prune the host database.  */
++  if (dbs[hstdb].enabled)
+     prune_cache (&dbs[hstdb], LONG_MAX);
+ }
diff --git a/src/patches/glibc/glibc-nscd-SIGHUP.patch b/src/patches/glibc/glibc-nscd-SIGHUP.patch
new file mode 100644 (file)
index 0000000..ce583fb
--- /dev/null
@@ -0,0 +1,81 @@
+2006-07-02  Jakub Jelinek  <jakub@redhat.com>
+
+       * nscd/connections.c (sighup_pending): New variable.
+       (nscd_run): If sighup_pending, prune all 3 caches.
+       (sighup_handler): Don't prune caches here, rather just set
+       sighup_pending flag.
+
+--- libc/nscd/connections.c.jj 2006-07-02 11:47:20.000000000 +0200
++++ libc/nscd/connections.c    2006-07-02 12:57:22.000000000 +0200
+@@ -66,6 +67,7 @@ static gid_t *server_groups;
+ # define NGROUPS 32
+ #endif
+ static int server_ngroups;
++static volatile int sighup_pending;
+ static pthread_attr_t attr;
+@@ -1283,6 +1285,10 @@ nscd_run (void *p)
+             if (readylist == NULL && to == ETIMEDOUT)
+               {
+                 --nready;
++
++                if (sighup_pending)
++                  goto sighup_prune;
++
+                 pthread_mutex_unlock (&readylist_lock);
+                 goto only_prune;
+               }
+@@ -1292,6 +1298,34 @@ nscd_run (void *p)
+           pthread_cond_wait (&readylist_cond, &readylist_lock);
+       }
++      if (sighup_pending)
++      {
++        --nready;
++        pthread_cond_signal (&readylist_cond);
++      sighup_prune:
++        sighup_pending = 0;
++        pthread_mutex_unlock (&readylist_lock);
++
++        /* Prune the password database.  */
++        if (dbs[pwddb].enabled)
++          prune_cache (&dbs[pwddb], LONG_MAX, -1);
++
++        /* Prune the group database.  */
++        if (dbs[grpdb].enabled)
++          prune_cache (&dbs[grpdb], LONG_MAX, -1);
++
++        /* Prune the host database.  */
++        if (dbs[hstdb].enabled)
++          prune_cache (&dbs[hstdb], LONG_MAX, -1);
++
++        /* Re-locking.  */
++        pthread_mutex_lock (&readylist_lock);
++
++        /* One more thread available.  */
++        ++nready;
++        continue;
++      }
++
+       struct fdlist *it = readylist->next;
+       if (readylist->next == readylist)
+       /* Just one entry on the list.  */
+@@ -1902,16 +1936,5 @@ finish_drop_privileges (void)
+ void
+ sighup_handler (int signum)
+ {
+-  /* Prune the password database.  */
+-  if (dbs[pwddb].enabled)
+-    prune_cache (&dbs[pwddb], LONG_MAX, -1);
+-    
+-  /* Prune the group database.  */
+-  if (dbs[grpdb].enabled)
+-    prune_cache (&dbs[grpdb], LONG_MAX, -1);
+-
+-  /* Prune the host database.  */
+-  if (dbs[hstdb].enabled)
+-    prune_cache (&dbs[hstdb], LONG_MAX, -1);
++  sighup_pending = 1;
+ }
+-
diff --git a/src/patches/glibc/glibc-nscd-addinitgroups.patch b/src/patches/glibc/glibc-nscd-addinitgroups.patch
new file mode 100644 (file)
index 0000000..9ee8ba2
--- /dev/null
@@ -0,0 +1,39 @@
+2006-09-05  Jakub Jelinek  <jakub@redhat.com>
+
+        * nscd/initgrcache.c (addinitgroupsX): Move any_success
+        decl before first goto out.
+
+2006-08-01  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2098]
+       * nscd/initgrcache.c (addinitgroupsX): Judge successful lookups by
+       status of NSS calls, not the number of returned entries.
+
+--- libc/nscd/initgrcache.c    6 Jan 2006 19:12:48 -0000       1.8
++++ libc/nscd/initgrcache.c    5 Sep 2006 14:35:00 -0000       1.10
+@@ -107,6 +107,7 @@ addinitgroupsX (struct database_dyn *db,
+   long int start = 0;
+   bool all_tryagain = true;
++  bool any_success = false;
+   /* This is temporary memory, we need not (ad must not) call
+      mempool_alloc.  */
+@@ -158,6 +159,8 @@ addinitgroupsX (struct database_dyn *db,
+       if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN)
+       __libc_fatal ("illegal status in internal_getgrouplist");
++      any_success |= status == NSS_STATUS_SUCCESS;
++
+       if (status != NSS_STATUS_SUCCESS
+         && nss_next_action (nip, status) == NSS_ACTION_RETURN)
+        break;
+@@ -171,7 +174,7 @@ addinitgroupsX (struct database_dyn *db,
+   ssize_t total;
+   ssize_t written;
+  out:
+-  if (start == 0)
++  if (!any_success)
+     {
+       /* Nothing found.  Create a negative result record.  */
+       written = total = sizeof (notfound);
diff --git a/src/patches/glibc/glibc-nscd-auto-propagate.patch b/src/patches/glibc/glibc-nscd-auto-propagate.patch
new file mode 100644 (file)
index 0000000..aa88446
--- /dev/null
@@ -0,0 +1,197 @@
+2006-04-27  Jakub Jelinek  <jakub@redhat.com>
+
+       * nscd/nscd.conf: Fix a typo.
+
+2006-04-26  Ulrich Drepper  <drepper@redhat.com>
+
+       * nscd/nscd.h (struct database_dyn): Add propagate field.
+       * nscd/nscd_conf.c (nscd_parse_file): Parse auto-propagate lines.
+       * nscd/nscd.conf: Add auto-propagate lines.
+       * nscd/connections.c (dbs): Initialize .propagate fields.
+       * nscd/grpcache.c (cache_addgr): Do not add ID entry for name lookups
+       and vice versa if propagation is disabled for the database.
+       * nscd/pwdcache.c (cache_addpw): Likewise.
+
+--- libc/nscd/connections.c    26 Apr 2006 16:26:17 -0000      1.84
++++ libc/nscd/connections.c    26 Apr 2006 17:28:50 -0000      1.85
+@@ -103,6 +103,7 @@ struct database_dyn dbs[lastdb] =
+     .enabled = 0,
+     .check_file = 1,
+     .persistent = 0,
++    .propagate = 1,
+     .shared = 0,
+     .max_db_size = DEFAULT_MAX_DB_SIZE,
+     .filename = "/etc/passwd",
+@@ -119,6 +120,7 @@ struct database_dyn dbs[lastdb] =
+     .enabled = 0,
+     .check_file = 1,
+     .persistent = 0,
++    .propagate = 1,
+     .shared = 0,
+     .max_db_size = DEFAULT_MAX_DB_SIZE,
+     .filename = "/etc/group",
+@@ -135,6 +137,7 @@ struct database_dyn dbs[lastdb] =
+     .enabled = 0,
+     .check_file = 1,
+     .persistent = 0,
++    .propagate = 0,           /* Not used.  */
+     .shared = 0,
+     .max_db_size = DEFAULT_MAX_DB_SIZE,
+     .filename = "/etc/hosts",
+--- libc/nscd/grpcache.c       6 Jan 2006 19:12:48 -0000       1.45
++++ libc/nscd/grpcache.c       26 Apr 2006 17:25:07 -0000      1.46
+@@ -342,10 +342,10 @@ cache_addgr (struct database_dyn *db, in
+            marked with FIRST first.  Otherwise we end up with
+            dangling "pointers" in case a latter hash entry cannot be
+            added.  */
+-        bool first = req->type == GETGRBYNAME;
++        bool first = true;
+         /* If the request was by GID, add that entry first.  */
+-        if (req->type != GETGRBYNAME)
++        if (req->type == GETGRBYGID)
+           {
+             if (cache_add (GETGRBYGID, cp, key_offset, &dataset->head, true,
+                            db, owner) < 0)
+@@ -355,12 +355,14 @@ cache_addgr (struct database_dyn *db, in
+                 dataset->head.usable = false;
+                 goto out;
+               }
++
++            first = false;
+           }
+         /* If the key is different from the name add a separate entry.  */
+         else if (strcmp (key_copy, gr_name) != 0)
+           {
+             if (cache_add (GETGRBYNAME, key_copy, key_len + 1,
+-                           &dataset->head, first, db, owner) < 0)
++                           &dataset->head, true, db, owner) < 0)
+               {
+                 /* Could not allocate memory.  Make sure the data gets
+                    discarded.  */
+@@ -372,11 +374,13 @@ cache_addgr (struct database_dyn *db, in
+           }
+         /* We have to add the value for both, byname and byuid.  */
+-        if (__builtin_expect (cache_add (GETGRBYNAME, gr_name, gr_name_len,
+-                                         &dataset->head, first, db, owner)
+-                              == 0, 1))
++        if ((req->type == GETGRBYNAME || db->propagate)
++            && __builtin_expect (cache_add (GETGRBYNAME, gr_name,
++                                            gr_name_len,
++                                            &dataset->head, first, db, owner)
++                                 == 0, 1))
+           {
+-            if (req->type == GETGRBYNAME)
++            if (req->type == GETGRBYNAME && db->propagate)
+               (void) cache_add (GETGRBYGID, cp, key_offset, &dataset->head,
+                                 req->type != GETGRBYNAME, db, owner);
+           }
+--- libc/nscd/nscd.conf        23 Aug 2005 23:17:32 -0000      1.11
++++ libc/nscd/nscd.conf        26 Apr 2006 17:27:03 -0000      1.13
+@@ -23,7 +23,8 @@
+ #     check-files             <service> <yes|no>
+ #     persistent              <service> <yes|no>
+ #     shared                  <service> <yes|no>
+ #     max-db-size             <service> <number bytes>
++#     auto-propagate          <service> <yes|no>
+ #
+ # Currently supported cache names (services): passwd, group, hosts
+ #
+@@ -47,6 +48,7 @@
+       persistent              passwd          yes
+       shared                  passwd          yes
+       max-db-size             passwd          33554432
++      auto-propagate          passwd          yes
+       enable-cache            group           yes
+       positive-time-to-live   group           3600
+@@ -56,6 +58,7 @@
+       persistent              group           yes
+       shared                  group           yes
+       max-db-size             group           33554432
++      auto-propagate          group           yes
+       enable-cache            hosts           yes
+       positive-time-to-live   hosts           3600
+--- libc/nscd/nscd.h   30 Dec 2005 16:51:19 -0000      1.24
++++ libc/nscd/nscd.h   26 Apr 2006 17:25:43 -0000      1.25
+@@ -63,6 +63,7 @@ struct database_dyn
+   int check_file;
+   int persistent;
+   int shared;
++  int propagate;
+   size_t max_db_size;
+   const char *filename;
+   const char *db_filename;
+--- libc/nscd/nscd_conf.c      7 Dec 2005 05:47:27 -0000       1.19
++++ libc/nscd/nscd_conf.c      26 Apr 2006 17:26:24 -0000      1.20
+@@ -182,6 +182,20 @@ nscd_parse_file (const char *fname, stru
+         if (cnt == lastdb)
+           dbg_log ("database %s is not supported\n", arg1);
+       }
++      else if (strcmp (entry, "auto-propagate") == 0)
++      {
++        for (cnt = 0; cnt < lastdb; ++cnt)
++          if (strcmp (arg1, dbnames[cnt]) == 0)
++            {
++              if (strcmp (arg2, "no") == 0)
++                dbs[cnt].propagate = 0;
++              else if (strcmp (arg2, "yes") == 0)
++                dbs[cnt].propagate = 1;
++              break;
++            }
++        if (cnt == lastdb)
++          dbg_log ("database %s is not supported\n", arg1);
++      }
+       else if (strcmp (entry, "logfile") == 0)
+       set_logfile (arg1);
+       else if (strcmp (entry, "debug-level") == 0)
+--- libc/nscd/pwdcache.c       6 Jan 2006 19:12:48 -0000       1.43
++++ libc/nscd/pwdcache.c       26 Apr 2006 17:27:51 -0000      1.44
+@@ -338,10 +338,10 @@ cache_addpw (struct database_dyn *db, in
+            marked with FIRST first.  Otherwise we end up with
+            dangling "pointers" in case a latter hash entry cannot be
+            added.  */
+-        bool first = req->type == GETPWBYNAME;
++        bool first = true;
+         /* If the request was by UID, add that entry first.  */
+-        if (req->type != GETPWBYNAME)
++        if (req->type == GETPWBYUID)
+           {
+             if (cache_add (GETPWBYUID, cp, key_offset, &dataset->head, true,
+                            db, owner) < 0)
+@@ -351,12 +351,14 @@ cache_addpw (struct database_dyn *db, in
+                 dataset->head.usable = false;
+                 goto out;
+               }
++
++            first = false;
+           }
+         /* If the key is different from the name add a separate entry.  */
+         else if (strcmp (key_copy, dataset->strdata) != 0)
+           {
+             if (cache_add (GETPWBYNAME, key_copy, key_len + 1,
+-                           &dataset->head, first, db, owner) < 0)
++                           &dataset->head, true, db, owner) < 0)
+               {
+                 /* Could not allocate memory.  Make sure the data gets
+                    discarded.  */
+@@ -368,11 +370,12 @@ cache_addpw (struct database_dyn *db, in
+           }
+         /* We have to add the value for both, byname and byuid.  */
+-        if (__builtin_expect (cache_add (GETPWBYNAME, dataset->strdata,
+-                                         pw_name_len, &dataset->head, first,
+-                                         db, owner) == 0, 1))
++        if ((req->type == GETPWBYNAME || db->propagate)
++            && __builtin_expect (cache_add (GETPWBYNAME, dataset->strdata,
++                                            pw_name_len, &dataset->head,
++                                            first, db, owner) == 0, 1))
+           {
+-            if (req->type == GETPWBYNAME)
++            if (req->type == GETPWBYNAME && db->propagate)
+               (void) cache_add (GETPWBYUID, cp, key_offset, &dataset->head,
+                                 req->type != GETPWBYNAME, db, owner);
+           }
diff --git a/src/patches/glibc/glibc-nscd-db-checker.patch b/src/patches/glibc/glibc-nscd-db-checker.patch
new file mode 100644 (file)
index 0000000..2257195
--- /dev/null
@@ -0,0 +1,298 @@
+2005-08-08  Ulrich Drepper  <drepper@redhat.com>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       * nscd/mem.c (BLOCK_ALIGN_LOG, BLOCK_ALIGN, BLOCK_ALIGN_M1): Move
+       definitions to...
+       * nscd/nscd.h (BLOCK_ALIGN_LOG, BLOCK_ALIGN, BLOCK_ALIGN_M1): ...here.
+       * nscd/connections.c (usekey): New enum.
+       (check_use, verify_persistent_db): New functions.
+       (nscd_init): If persistent database is corrupted, unlink it and
+       recreate rather than falling back to non-persistent database.
+       Call verify_persistent_db.  Avoid overflows in total computation.
+
+--- libc/nscd/connections.c    18 Jul 2005 22:25:16 -0000      1.70
++++ libc/nscd/connections.c    8 Aug 2005 18:56:17 -0000       1.71
+@@ -199,6 +199,210 @@ writeall (int fd, const void *buf, size_
+ }
++enum usekey
++  {
++    use_not = 0,
++    /* The following three are not really used, they are symbolic constants.  */
++    use_first = 16,
++    use_begin = 32,
++    use_end = 64,
++
++    use_he = 1,
++    use_he_begin = use_he | use_begin,
++    use_he_end = use_he | use_end,
++#if SEPARATE_KEY
++    use_key = 2,
++    use_key_begin = use_key | use_begin,
++    use_key_end = use_key | use_end,
++    use_key_first = use_key_begin | use_first,
++#endif
++    use_data = 3,
++    use_data_begin = use_data | use_begin,
++    use_data_end = use_data | use_end,
++    use_data_first = use_data_begin | use_first
++  };
++
++
++static int
++check_use (const char *data, nscd_ssize_t first_free, uint8_t *usemap,
++         enum usekey use, ref_t start, size_t len)
++{
++  assert (len >= 2);
++
++  if (start > first_free || start + len > first_free
++      || (start & BLOCK_ALIGN_M1))
++    return 0;
++
++  if (usemap[start] == use_not)
++    {
++      /* Add the start marker.  */
++      usemap[start] = use | use_begin;
++      use &= ~use_first;
++
++      while (--len > 0)
++      if (usemap[++start] != use_not)
++        return 0;
++      else
++        usemap[start] = use;
++
++      /* Add the end marker.  */
++      usemap[start] = use | use_end;
++    }
++  else if ((usemap[start] & ~use_first) == ((use | use_begin) & ~use_first))
++    {
++      /* Hash entries can't be shared.  */
++      if (use == use_he)
++      return 0;
++
++      usemap[start] |= (use & use_first);
++      use &= ~use_first;
++
++      while (--len > 1)
++      if (usemap[++start] != use)
++        return 0;
++
++      if (usemap[++start] != (use | use_end))
++      return 0;
++    }
++  else
++    /* Points to a wrong object or somewhere in the middle.  */
++    return 0;
++
++  return 1;
++}
++
++
++/* Verify data in persistent database.  */
++static int
++verify_persistent_db (void *mem, struct database_pers_head *readhead, int dbnr)
++{
++  assert (dbnr == pwddb || dbnr == grpdb || dbnr == hstdb);
++
++  time_t now = time (NULL);
++
++  struct database_pers_head *head = mem;
++  struct database_pers_head head_copy = *head;
++
++  /* Check that the header that was read matches the head in the database.  */
++  if (readhead != NULL && memcmp (head, readhead, sizeof (*head)) != 0)
++    return 0;
++
++  /* First some easy tests: make sure the database header is sane.  */
++  if (head->version != DB_VERSION
++      || head->header_size != sizeof (*head)
++      /* We allow a timestamp to be one hour ahead of the current time.
++       This should cover daylight saving time changes.  */
++      || head->timestamp > now + 60 * 60 + 60
++      || (head->gc_cycle & 1)
++      || (size_t) head->module > INT32_MAX / sizeof (ref_t)
++      || (size_t) head->data_size > INT32_MAX - head->module * sizeof (ref_t)
++      || head->first_free < 0
++      || head->first_free > head->data_size
++      || (head->first_free & BLOCK_ALIGN_M1) != 0
++      || head->maxnentries < 0
++      || head->maxnsearched < 0)
++    return 0;
++
++  uint8_t *usemap = calloc (head->first_free, 1);
++  if (usemap == NULL)
++    return 0;
++
++  const char *data = (char *) &head->array[roundup (head->module,
++                                                  ALIGN / sizeof (ref_t))];
++
++  nscd_ssize_t he_cnt = 0;
++  for (nscd_ssize_t cnt = 0; cnt < head->module; ++cnt)
++    {
++      ref_t work = head->array[cnt];
++
++      while (work != ENDREF)
++      {
++        if (! check_use (data, head->first_free, usemap, use_he, work,
++                         sizeof (struct hashentry)))
++          goto fail;
++
++        /* Now we know we can dereference the record.  */
++        struct hashentry *here = (struct hashentry *) (data + work);
++
++        ++he_cnt;
++
++        /* Make sure the record is for this type of service.  */
++        if (here->type >= LASTREQ
++            || serv2db[here->type] != &dbs[dbnr])
++          goto fail;
++
++        /* Validate boolean field value.  */
++        if (here->first != false && here->first != true)
++          goto fail;
++
++        if (here->len < 0)
++          goto fail;
++
++        /* Now the data.  */
++        if (here->packet < 0
++            || here->packet > head->first_free
++            || here->packet + sizeof (struct datahead) > head->first_free)
++          goto fail;
++
++        struct datahead *dh = (struct datahead *) (data + here->packet);
++
++        if (! check_use (data, head->first_free, usemap,
++                         use_data | (here->first ? use_first : 0),
++                         here->packet, dh->allocsize))
++          goto fail;
++
++        if (dh->allocsize < sizeof (struct datahead)
++            || dh->recsize > dh->allocsize
++            || (dh->notfound != false && dh->notfound != true)
++            || (dh->usable != false && dh->usable != true))
++          goto fail;
++
++        if (here->key < here->packet + sizeof (struct datahead)
++            || here->key > here->packet + dh->allocsize
++            || here->key + here->len > here->packet + dh->allocsize)
++          {
++#if SEPARATE_KEY
++            /* If keys can appear outside of data, this should be done
++               instead.  But gc doesn't mark the data in that case.  */
++            if (! check_use (data, head->first_free, usemap,
++                             use_key | (here->first ? use_first : 0),
++                             here->key, here->len))
++#endif
++              goto fail;
++          }
++
++        work = here->next;
++      }
++    }
++
++  if (he_cnt != head->nentries)
++    goto fail;
++
++  /* See if all data and keys had at least one reference from
++     he->first == true hashentry.  */
++  for (ref_t idx = 0; idx < head->first_free; ++idx)
++    {
++#if SEPARATE_KEY
++      if (usemap[idx] == use_key_begin)
++      goto fail;
++#endif
++      if (usemap[idx] == use_data_begin)
++      goto fail;
++    }
++
++  /* Finally, make sure the database hasn't changed since the first test.  */
++  if (memcmp (mem, &head_copy, sizeof (*head)) != 0)
++    goto fail;
++
++  free (usemap);
++  return 1;
++
++fail:
++  free (usemap);
++  return 0;
++}
++
++
+ /* Initialize database information structures.  */
+ void
+ nscd_init (void)
+@@ -242,7 +446,7 @@ nscd_init (void)
+                 fail_db:
+                   dbg_log (_("invalid persistent database file \"%s\": %s"),
+                            dbs[cnt].db_filename, strerror (errno));
+-                  dbs[cnt].persistent = 0;
++                  unlink (dbs[cnt].db_filename);
+                 }
+               else if (head.module == 0 && head.data_size == 0)
+                 {
+@@ -255,22 +459,31 @@ nscd_init (void)
+                   dbg_log (_("invalid persistent database file \"%s\": %s"),
+                            dbs[cnt].db_filename,
+                            _("header size does not match"));
+-                  dbs[cnt].persistent = 0;
++                  unlink (dbs[cnt].db_filename);
+                 }
+               else if ((total = (sizeof (head)
+                                  + roundup (head.module * sizeof (ref_t),
+                                             ALIGN)
+                                  + head.data_size))
+-                       > st.st_size)
++                       > st.st_size
++                       || total < sizeof (head))
+                 {
+                   dbg_log (_("invalid persistent database file \"%s\": %s"),
+                            dbs[cnt].db_filename,
+                            _("file size does not match"));
+-                  dbs[cnt].persistent = 0;
++                  unlink (dbs[cnt].db_filename);
+                 }
+               else if ((mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
+                                     MAP_SHARED, fd, 0)) == MAP_FAILED)
+                 goto fail_db;
++              else if (!verify_persistent_db (mem, &head, cnt))
++                {
++                  munmap (mem, total);
++                  dbg_log (_("invalid persistent database file \"%s\": %s"),
++                           dbs[cnt].db_filename,
++                           _("verification failed"));
++                  unlink (dbs[cnt].db_filename);
++                }
+               else
+                 {
+                   /* Success.  We have the database.  */
+--- libc/nscd/mem.c    7 Aug 2005 21:16:45 -0000       1.4
++++ libc/nscd/mem.c    8 Aug 2005 18:55:26 -0000       1.5
+@@ -34,12 +34,6 @@
+ #include "nscd.h"
+-/* Maximum alignment requirement we will encounter.  */
+-#define BLOCK_ALIGN_LOG 3
+-#define BLOCK_ALIGN (1 << BLOCK_ALIGN_LOG)
+-#define BLOCK_ALIGN_M1 (BLOCK_ALIGN - 1)
+-
+-
+ static int
+ sort_he (const void *p1, const void *p2)
+ {
+--- libc/nscd/nscd.h   15 Oct 2004 21:13:19 -0000      1.21
++++ libc/nscd/nscd.h   8 Aug 2005 18:54:44 -0000       1.22
+@@ -94,6 +94,11 @@ struct database_dyn
+ /* Path used when not using persistent storage.  */
+ #define _PATH_NSCD_XYZ_DB_TMP "/var/run/nscd/dbXXXXXX"
++/* Maximum alignment requirement we will encounter.  */
++#define BLOCK_ALIGN_LOG 3
++#define BLOCK_ALIGN (1 << BLOCK_ALIGN_LOG)
++#define BLOCK_ALIGN_M1 (BLOCK_ALIGN - 1)
++
+ /* Global variables.  */
+ extern struct database_dyn dbs[lastdb];
diff --git a/src/patches/glibc/glibc-nscd-debug-verbose.patch b/src/patches/glibc/glibc-nscd-debug-verbose.patch
new file mode 100644 (file)
index 0000000..2ab5a16
--- /dev/null
@@ -0,0 +1,52 @@
+2005-08-16  Ulrich Drepper  <drepper@redhat.com>
+
+       * nscd/cache.c (prune_cache): Add more debug output.  Only for
+       debug level 3 and higher and very verbose.
+
+--- libc/nscd/cache.c  16 Aug 2005 18:08:41 -0000      1.22
++++ libc/nscd/cache.c  16 Aug 2005 22:46:16 -0000      1.23
+@@ -21,6 +21,7 @@
+ #include <atomic.h>
+ #include <errno.h>
+ #include <error.h>
++#include <inttypes.h>
+ #include <limits.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -238,6 +239,10 @@ prune_cache (struct database_dyn *table,
+   char *const data = table->data;
+   bool any = false;
++  if (__builtin_expect (debug_level > 2, 0))
++    dbg_log (_("pruning %s cache; time %ld"),
++           dbnames[table - dbs], (long int) now);
++
+   do
+     {
+       ref_t run = table->head->array[--cnt];
+@@ -247,6 +252,25 @@ prune_cache (struct database_dyn *table,
+         struct hashentry *runp = (struct hashentry *) (data + run);
+         struct datahead *dh = (struct datahead *) (data + runp->packet);
++        /* Some debug support.  */
++        if (__builtin_expect (debug_level > 2, 0))
++          {
++            char buf[INET6_ADDRSTRLEN];
++            const char *str;
++
++            if (runp->type == GETHOSTBYADDR || runp->type == GETHOSTBYADDRv6)
++              {
++                inet_ntop (runp->type == GETHOSTBYADDR ? AF_INET : AF_INET6,
++                           data + runp->key, buf, sizeof (buf));
++                str = buf;
++              }
++            else
++              str = data + runp->key;
++
++            dbg_log (_("considering %s entry \"%s\", timeout %" PRIu64),
++                     serv2str[runp->type], str, dh->timeout);
++          }
++
+         /* Check whether the entry timed out.  */
+         if (dh->timeout < now)
+           {
diff --git a/src/patches/glibc/glibc-nscd-fallocate.patch b/src/patches/glibc/glibc-nscd-fallocate.patch
new file mode 100644 (file)
index 0000000..822f485
--- /dev/null
@@ -0,0 +1,36 @@
+2005-08-08  Ulrich Drepper  <drepper@redhat.com>
+
+       * nscd/mem.c (mempool_alloc): Use posix_fallocate instead of ftruncate.
+       * nscd/connections.c (nscd_init): Likewise.
+
+--- libc/nscd/connections.c    8 Aug 2005 18:56:17 -0000       1.71
++++ libc/nscd/connections.c    8 Aug 2005 20:40:53 -0000       1.72
+@@ -638,7 +638,7 @@ cannot create read-only descriptor for \
+               if ((TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head)))
+                    != sizeof (head))
+-                  || ftruncate (fd, total) != 0
++                  || posix_fallocate (fd, 0, total) != 0
+                   || (mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
+                                   MAP_SHARED, fd, 0)) == MAP_FAILED)
+                 {
+--- libc/nscd/mem.c    8 Aug 2005 18:55:26 -0000       1.5
++++ libc/nscd/mem.c    8 Aug 2005 20:38:42 -0000       1.6
+@@ -21,6 +21,7 @@
+ #include <assert.h>
+ #include <errno.h>
+ #include <error.h>
++#include <fcntl.h>
+ #include <inttypes.h>
+ #include <libintl.h>
+ #include <limits.h>
+@@ -488,7 +489,8 @@ mempool_alloc (struct database_dyn *db, 
+                            + db->head->module * sizeof (ref_t)
+                            + new_data_size);
+-        if ((!db->mmap_used || ftruncate (db->wr_fd, newtotal) != 0)
++        if ((!db->mmap_used
++             || posix_fallocate (db->wr_fd, oldtotal, newtotal) != 0)
+             /* Try to resize the mapping.  Note: no MREMAP_MAYMOVE.  */
+             && mremap (db->head, oldtotal, newtotal, 0) == 0)
+           {
diff --git a/src/patches/glibc/glibc-nscd-getpw_r-retry.patch b/src/patches/glibc/glibc-nscd-getpw_r-retry.patch
new file mode 100644 (file)
index 0000000..0e71609
--- /dev/null
@@ -0,0 +1,17 @@
+2005-09-22  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1363]
+       * nscd/nscd_getpw_r.c (nscd_getpw_r): Remove incorrectly C&Ped
+       free call in code handling detection of GC runs.
+
+--- libc/nscd/nscd_getpw_r.c   22 Feb 2005 22:47:45 -0000      1.30
++++ libc/nscd/nscd_getpw_r.c   22 Sep 2005 14:35:11 -0000      1.31
+@@ -227,8 +227,6 @@ nscd_getpw_r (const char *key, size_t ke
+         mapped = NO_MAPPING;
+       }
+-      free (resultbuf);
+-
+       goto retry;
+     }
diff --git a/src/patches/glibc/glibc-nscd-hst-noalias.patch b/src/patches/glibc/glibc-nscd-hst-noalias.patch
new file mode 100644 (file)
index 0000000..6f2573a
--- /dev/null
@@ -0,0 +1,19 @@
+2005-11-19  Ulrich Drepper  <drepper@redhat.com>
+
+       * nscd/nscd_gethst_r.c (nscd_gethst_r): Avoid unnecesary read call
+       if there are no aliases.
+
+--- libc/nscd/nscd_gethst_r.c  22 Feb 2005 22:47:45 -0000      1.32
++++ libc/nscd/nscd_gethst_r.c  19 Nov 2005 17:09:03 -0000      1.33
+@@ -328,8 +328,9 @@ nscd_gethst_r (const char *key, size_t k
+       /* And finally read the aliases.  */
+       if (addr_list == NULL)
+       {
+-        if ((size_t) __readall (sock, resultbuf->h_aliases[0], total_len)
+-            == total_len)
++        if (total_len == 0
++            || ((size_t) __readall (sock, resultbuf->h_aliases[0], total_len)
++                == total_len))
+           {
+             retval = 0;
+             *result = resultbuf;
diff --git a/src/patches/glibc/glibc-nscd-max-db-size.patch b/src/patches/glibc/glibc-nscd-max-db-size.patch
new file mode 100644 (file)
index 0000000..932f6be
--- /dev/null
@@ -0,0 +1,217 @@
+2005-08-23  Ulrich Drepper  <drepper@redhat.com>
+
+       * nscd/connection.c (DEFAULT_DATASIZE_PER_BUCKET): Move to nscd.h.
+       (dbs): Initialize max_db_size fields.
+       (nscd_init): When mapping the database, use max_db_size as the
+       mapping size even if it is bigger than the file size.
+       * nscd/mem.c (mempool_alloc): When resizing the file make sure the
+       limit in max_db_size is not exceeded.  Don't use mremap, just
+       posix_fallocate is enough (according to Linus).  Use posix_fallocate
+       correctly.
+       * nscd/nscd.conf: Add max-db-size parameters.
+       * nscd/nscd.h (struct database_dyn): Add max_db_size field.
+       Define DEFAULT_MAX_DB_SIZE and DEFAULT_DATASIZE_PER_BUCKET.
+       Temporarily define TEMP_FAILURE_RETRY_VAL here.
+       * nscd/nscd_conf.c (nscd_parse_file): Parse max-db-size parameter
+       and add sanity checks for it.
+
+--- libc/nscd/mem.c    8 Aug 2005 20:38:42 -0000       1.6
++++ libc/nscd/mem.c    23 Aug 2005 23:15:28 -0000      1.7
+@@ -481,21 +481,26 @@ mempool_alloc (struct database_dyn *db, 
+       if (! tried_resize)
+       {
+         /* Try to resize the database.  Grow size of 1/8th.  */
+-        size_t new_data_size = db->head->data_size + db->head->data_size / 8;
++        size_t new_data_size = (db->head->data_size
++                                + MAX (2 * len, db->head->data_size / 8));
+         size_t oldtotal = (sizeof (struct database_pers_head)
+                            + db->head->module * sizeof (ref_t)
+                            + db->head->data_size);
+         size_t newtotal = (sizeof (struct database_pers_head)
+                            + db->head->module * sizeof (ref_t)
+                            + new_data_size);
++        if (newtotal > db->max_db_size)
++          {
++            new_data_size -= newtotal - db->max_db_size;
++            newtotal = db->max_db_size;
++          }
+-        if ((!db->mmap_used
+-             || TEMP_FAILURE_RETRY_VAL (posix_fallocate (db->wr_fd,
+-                                                         oldtotal,
+-                                                         newtotal - oldtotal))
+-                                        != 0)
+-            /* Try to resize the mapping.  Note: no MREMAP_MAYMOVE.  */
+-            && mremap (db->head, oldtotal, newtotal, 0) == 0)
++        if (db->mmap_used && newtotal > oldtotal
++            /* We only have to adjust the file size.  The new pages
++               become magically available.  */
++            && TEMP_FAILURE_RETRY_VAL (posix_fallocate (db->wr_fd, oldtotal,
++                                                        newtotal
++                                                        - oldtotal)) == 0)
+           {
+             db->head->data_size = new_data_size;
+             tried_resize = true;
+--- libc/nscd/nscd.conf        3 Oct 2004 21:09:23 -0000       1.10
++++ libc/nscd/nscd.conf        23 Aug 2005 23:17:32 -0000      1.11
+@@ -23,6 +23,7 @@
+ #     check-files             <service> <yes|no>
+ #     persistent              <service> <yes|no>
+ #     shared                  <service> <yes|no>
++#     max-db-size             <service> <number bytes>
+ #
+ # Currently supported cache names (services): passwd, group, hosts
+ #
+@@ -45,6 +46,7 @@
+       check-files             passwd          yes
+       persistent              passwd          yes
+       shared                  passwd          yes
++      max-db-size             passwd          33554432
+       enable-cache            group           yes
+       positive-time-to-live   group           3600
+@@ -53,6 +55,7 @@
+       check-files             group           yes
+       persistent              group           yes
+       shared                  group           yes
++      max-db-size             group           33554432
+       enable-cache            hosts           yes
+       positive-time-to-live   hosts           3600
+@@ -61,3 +64,4 @@
+       check-files             hosts           yes
+       persistent              hosts           yes
+       shared                  hosts           yes
++      max-db-size             hosts           33554432
+--- libc/nscd/nscd.h   8 Aug 2005 18:54:44 -0000       1.22
++++ libc/nscd/nscd.h   23 Aug 2005 23:18:23 -0000      1.23
+@@ -63,6 +63,7 @@ struct database_dyn
+   int check_file;
+   int persistent;
+   int shared;
++  size_t max_db_size;
+   const char *filename;
+   const char *db_filename;
+   time_t file_mtime;
+@@ -99,6 +100,12 @@ struct database_dyn
+ #define BLOCK_ALIGN (1 << BLOCK_ALIGN_LOG)
+ #define BLOCK_ALIGN_M1 (BLOCK_ALIGN - 1)
++/* Default value for the maximum size of the database files.  */
++#define DEFAULT_MAX_DB_SIZE   (32 * 1024 * 1024)
++
++/* Number of bytes of data we initially reserve for each hash table bucket.  */
++#define DEFAULT_DATASIZE_PER_BUCKET 1024
++
+ /* Global variables.  */
+ extern struct database_dyn dbs[lastdb];
+--- libc/nscd/nscd_conf.c      3 Oct 2004 21:10:35 -0000       1.16
++++ libc/nscd/nscd_conf.c      23 Aug 2005 23:19:14 -0000      1.17
+@@ -171,6 +171,17 @@ nscd_parse_file (const char *fname, stru
+         if (cnt == lastdb)
+           dbg_log ("database %s is not supported\n", arg1);
+       }
++      else if (strcmp (entry, "max-db-size") == 0)
++      {
++        for (cnt = 0; cnt < lastdb; ++cnt)
++          if (strcmp (arg1, dbnames[cnt]) == 0)
++            {
++              dbs[cnt].max_db_size = atol (arg2);
++              break;
++            }
++        if (cnt == lastdb)
++          dbg_log ("database %s is not supported\n", arg1);
++      }
+       else if (strcmp (entry, "logfile") == 0)
+       set_logfile (arg1);
+       else if (strcmp (entry, "debug-level") == 0)
+@@ -293,6 +304,22 @@ cannot get current working directory: %s
+   if (max_nthreads < nthreads)
+     max_nthreads = nthreads;
++  for (cnt = 0; cnt < lastdb; ++cnt)
++    {
++      size_t datasize = (sizeof (struct database_pers_head)
++                       + roundup (dbs[cnt].suggested_module
++                                  * sizeof (ref_t), ALIGN)
++                       + (dbs[cnt].suggested_module
++                          * DEFAULT_DATASIZE_PER_BUCKET));
++      if (datasize > dbs[cnt].max_db_size)
++      {
++        dbg_log (_("maximum file size for %s database too small"),
++                 dbnames[cnt]);
++        dbs[cnt].max_db_size = datasize;
++      }
++
++    }
++
+   /* Free the buffer.  */
+   free (line);
+   /* Close configuration file.  */
+--- libc/nscd/connections.c    16 Aug 2005 18:07:46 -0000      1.75
++++ libc/nscd/connections.c    23 Aug 2005 23:12:00 -0000      1.76
+@@ -50,10 +50,6 @@
+ #include "selinux.h"
+-/* Number of bytes of data we initially reserve for each hash table bucket.  */
+-#define DEFAULT_DATASIZE_PER_BUCKET 1024
+-
+-
+ /* Wrapper functions with error checking for standard functions.  */
+ extern void *xmalloc (size_t n);
+ extern void *xcalloc (size_t n, size_t s);
+@@ -107,6 +103,7 @@ struct database_dyn dbs[lastdb] =
+     .persistent = 0,
+     .propagate = 1,
+     .shared = 0,
++    .max_db_size = DEFAULT_MAX_DB_SIZE,
+     .filename = "/etc/passwd",
+     .db_filename = _PATH_NSCD_PASSWD_DB,
+     .disabled_iov = &pwd_iov_disabled,
+@@ -123,6 +120,7 @@ struct database_dyn dbs[lastdb] =
+     .persistent = 0,
+     .propagate = 1,
+     .shared = 0,
++    .max_db_size = DEFAULT_MAX_DB_SIZE,
+     .filename = "/etc/group",
+     .db_filename = _PATH_NSCD_GROUP_DB,
+     .disabled_iov = &grp_iov_disabled,
+@@ -139,6 +137,7 @@ struct database_dyn dbs[lastdb] =
+     .persistent = 0,
+     .propagate = 0,           /* Not used.  */
+     .shared = 0,
++    .max_db_size = DEFAULT_MAX_DB_SIZE,
+     .filename = "/etc/hosts",
+     .db_filename = _PATH_NSCD_HOSTS_DB,
+     .disabled_iov = &hst_iov_disabled,
+@@ -478,8 +477,16 @@ nscd_init (void)
+                            _("file size does not match"));
+                   unlink (dbs[cnt].db_filename);
+                 }
+-              else if ((mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
+-                                    MAP_SHARED, fd, 0)) == MAP_FAILED)
++              /* Note we map with the maximum size allowed for the
++                 database.  This is likely much larger than the
++                 actual file size.  This is OK on most OSes since
++                 extensions of the underlying file will
++                 automatically translate more pages available for
++                 memory access.  */
++              else if ((mem = mmap (NULL, dbs[cnt].max_db_size,
++                                    PROT_READ | PROT_WRITE,
++                                    MAP_SHARED, fd, 0))
++                       == MAP_FAILED)
+                 goto fail_db;
+               else if (!verify_persistent_db (mem, &head, cnt))
+                 {
+@@ -642,7 +649,8 @@ cannot create read-only descriptor for \
+                    != sizeof (head))
+                   || (TEMP_FAILURE_RETRY_VAL (posix_fallocate (fd, 0, total))
+                       != 0)
+-                  || (mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
++                  || (mem = mmap (NULL, dbs[cnt].max_db_size,
++                                  PROT_READ | PROT_WRITE,
+                                   MAP_SHARED, fd, 0)) == MAP_FAILED)
+                 {
+                   unlink (dbs[cnt].db_filename);
diff --git a/src/patches/glibc/glibc-nscd-msync.patch b/src/patches/glibc/glibc-nscd-msync.patch
new file mode 100644 (file)
index 0000000..118f906
--- /dev/null
@@ -0,0 +1,19 @@
+2005-08-08  Ulrich Drepper  <drepper@redhat.com>
+       * nscd/cache.c (cache_add): Commit hash table and header to disk.
+
+--- libc/nscd/cache.c  30 Sep 2004 02:20:53 -0000      1.20
++++ libc/nscd/cache.c  8 Aug 2005 20:58:35 -0000       1.21
+@@ -169,6 +169,12 @@ cache_add (int type, const void *key, si
+   if (nentries > table->head->maxnentries)
+     table->head->maxnentries = nentries;
++  if (table->persistent)
++    // XXX async OK?
++    msync ((void *) table->head,
++         (char *) &table->head->array[hash] - (char *) table->head
++         + sizeof (ref_t), MS_ASYNC);
++
+   return 0;
+ }
diff --git a/src/patches/glibc/glibc-nscd-paranoia.patch b/src/patches/glibc/glibc-nscd-paranoia.patch
new file mode 100644 (file)
index 0000000..3f65235
--- /dev/null
@@ -0,0 +1,52 @@
+2006-04-27  Ulrich Drepper  <drepper@redhat.com>
+
+       * nscd/connections.c (restart): If we want to switch back to the
+       old ID use setresuid and setresgid.
+       (finish_drop_privileges): Likewise.
+
+--- libc/nscd/connections.c    26 Apr 2006 17:28:50 -0000      1.85
++++ libc/nscd/connections.c    27 Apr 2006 20:33:32 -0000      1.87
+@@ -1124,7 +1124,7 @@ cannot open /proc/self/cmdline: %s; disa
+   /* Second, change back to the old user if we changed it.  */
+   if (server_user != NULL)
+     {
+-      if (setuid (old_uid) != 0)
++      if (setresuid (old_uid, old_uid, old_uid) != 0)
+       {
+         dbg_log (_("\
+ cannot change to old UID: %s; disabling paranoia mode"),
+@@ -1134,7 +1134,7 @@ cannot change to old UID: %s; disabling 
+         return;
+       }
+-      if (setgid (old_gid) != 0)
++      if (setresgid (old_gid, old_gid, old_gid) != 0)
+       {
+         dbg_log (_("\
+ cannot change to old GID: %s; disabling paranoia mode"),
+@@ -1853,14 +1853,23 @@ finish_drop_privileges (void)
+       error (EXIT_FAILURE, errno, _("setgroups failed"));
+     }
+-  if (setgid (server_gid) == -1)
++  int res;
++  if (paranoia)
++    res = setresgid (server_gid, server_gid, old_gid);
++  else
++    res = setgid (server_gid);
++  if (res == -1)
+     {
+       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
+       perror ("setgid");
+       exit (1);
+     }
+-  if (setuid (server_uid) == -1)
++  if (paranoia)
++    res = setresuid (server_uid, server_uid, old_uid);
++  else
++    res = setuid (server_uid);
++  if (res == -1)
+     {
+       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
+       perror ("setuid");
diff --git a/src/patches/glibc/glibc-nscd-stat64.patch b/src/patches/glibc/glibc-nscd-stat64.patch
new file mode 100644 (file)
index 0000000..f86f83d
--- /dev/null
@@ -0,0 +1,33 @@
+2005-08-16  Ulrich Drepper  <drepper@redhat.com>
+
+       * nscd/cache.c (prune_cache): Use stat64 not stat.
+       * nscd/connections.c (nscd_init): Likewise.
+
+--- libc/nscd/cache.c  8 Aug 2005 20:58:35 -0000       1.21
++++ libc/nscd/cache.c  16 Aug 2005 18:08:41 -0000      1.22
+@@ -203,9 +203,9 @@ prune_cache (struct database_dyn *table,
+      the entries also in this case.  */
+   if (table->check_file)
+     {
+-      struct stat st;
++      struct stat64 st;
+-      if (stat (table->filename, &st) < 0)
++      if (stat64 (table->filename, &st) < 0)
+       {
+         char buf[128];
+         /* We cannot stat() the file, disable file checking if the
+--- libc/nscd/connections.c    9 Aug 2005 06:16:13 -0000       1.74
++++ libc/nscd/connections.c    16 Aug 2005 18:07:46 -0000      1.75
+@@ -710,9 +710,9 @@ cannot set socket to close on exec: %s; 
+       if (dbs[cnt].check_file)
+         {
+           /* We need the modification date of the file.  */
+-          struct stat st;
++          struct stat64 st;
+-          if (stat (dbs[cnt].filename, &st) < 0)
++          if (stat64 (dbs[cnt].filename, &st) < 0)
+             {
+               /* We cannot stat() the file, disable file checking.  */
+               dbg_log (_("cannot stat() file `%s': %s"),
diff --git a/src/patches/glibc/glibc-nscd-stats.patch b/src/patches/glibc/glibc-nscd-stats.patch
new file mode 100644 (file)
index 0000000..b7dc0b0
--- /dev/null
@@ -0,0 +1,41 @@
+2005-08-08  Ulrich Drepper  <drepper@redhat.com>
+
+       * nscd/nscd_stat.c (receive_print_stats): Really print values of
+       thread number, paranoia, and restart interval the server is using.
+
+--- libc/nscd/nscd_stat.c      26 Jun 2005 18:26:28 -0000      1.14
++++ libc/nscd/nscd_stat.c      9 Aug 2005 05:45:03 -0000       1.15
+@@ -75,6 +75,10 @@ struct statdata
+   int debug_level;
+   time_t runtime;
+   unsigned long int client_queued;
++  int nthreads;
++  int max_nthreads;
++  int paranoia;
++  time_t restart_interval;
+   int ndbs;
+   struct dbstat dbs[lastdb];
+ #ifdef HAVE_SELINUX
+@@ -93,6 +97,10 @@ send_stats (int fd, struct database_dyn 
+   data.debug_level = debug_level;
+   data.runtime = time (NULL) - start_time;
+   data.client_queued = client_queued;
++  data.nthreads = nthreads;
++  data.max_nthreads = max_nthreads;
++  data.paranoia = paranoia;
++  data.restart_interval = restart_interval;
+   data.ndbs = lastdb;
+   for (cnt = 0; cnt < lastdb; ++cnt)
+@@ -230,8 +238,9 @@ receive_print_stats (void)
+           "%15lu  number of times clients had to wait\n"
+           "%15s  paranoia mode enabled\n"
+           "%15lu  restart internal\n"),
+-        nthreads, max_nthreads, data.client_queued,
+-        paranoia ? yesstr : nostr, (unsigned long int) restart_interval);
++        data.nthreads, data.max_nthreads, data.client_queued,
++        data.paranoia ? yesstr : nostr,
++        (unsigned long int) data.restart_interval);
+   for (i = 0; i < lastdb; ++i)
+     {
diff --git a/src/patches/glibc/glibc-nsswitch_conf.patch b/src/patches/glibc/glibc-nsswitch_conf.patch
new file mode 100644 (file)
index 0000000..d470c8e
--- /dev/null
@@ -0,0 +1,72 @@
+--- libc/fedora/nsswitch.conf.jj       2004-09-22 21:17:12.000000000 -0400
++++ libc/fedora/nsswitch.conf  2005-07-04 12:20:44.000000000 -0400
+@@ -12,13 +12,14 @@
+ #
+ # Legal entries are:
+ #
+-#     nisplus or nis+         Use NIS+ (NIS version 3)
+ #     nis or yp               Use NIS (NIS version 2), also called YP
+ #     dns                     Use DNS (Domain Name Service)
+ #     files                   Use the local files
+ #     db                      Use the local database (.db) files
+ #     compat                  Use NIS on compat mode
+ #     hesiod                  Use Hesiod for user lookups
++#     ldap                    Use LDAP (only if nss_ldap is installed)
++#     nisplus or nis+         Use NIS+ (NIS version 3), unsupported
+ #     [NOTFOUND=return]       Stop searching if not found so far
+ #
+@@ -26,38 +27,32 @@
+ # looked up first in the databases
+ #
+ # Example:
+-#passwd:    db files nisplus nis
+-#shadow:    db files nisplus nis
+-#group:     db files nisplus nis
++#passwd:    db files ldap nis
++#shadow:    db files ldap nis
++#group:     db files ldap nis
+ passwd:     files
+ shadow:     files
+ group:      files
+-#hosts:     db files nisplus nis dns
++#hosts:     db files ldap nis dns
+ hosts:      files dns
+-# Example - obey only what nisplus tells us...
+-#services:   nisplus [NOTFOUND=return] files
+-#networks:   nisplus [NOTFOUND=return] files
+-#protocols:  nisplus [NOTFOUND=return] files
+-#rpc:        nisplus [NOTFOUND=return] files
+-#ethers:     nisplus [NOTFOUND=return] files
+-#netmasks:   nisplus [NOTFOUND=return] files     
+-
+-bootparams: nisplus [NOTFOUND=return] files
++# Example - obey only what ldap tells us...
++#services:  ldap [NOTFOUND=return] files
++#networks:  ldap [NOTFOUND=return] files
++#protocols: ldap [NOTFOUND=return] files
++#rpc:       ldap [NOTFOUND=return] files
++#ethers:    ldap [NOTFOUND=return] files
++bootparams: files
+ ethers:     files
+ netmasks:   files
+ networks:   files
+ protocols:  files
+ rpc:        files
+ services:   files
+-
+-netgroup:   nisplus
+-
+-publickey:  nisplus
+-
+-automount:  files nisplus
+-aliases:    files nisplus
+-
++netgroup:   files
++publickey:  files
++automount:  files
++aliases:    files
diff --git a/src/patches/glibc/glibc-obstack_h-typo.patch b/src/patches/glibc/glibc-obstack_h-typo.patch
new file mode 100644 (file)
index 0000000..c1b4b6a
--- /dev/null
@@ -0,0 +1,18 @@
+2005-09-12  Roland McGrath  <roland@redhat.com>
+
+       [BZ #1331]
+       * malloc/obstack.h [!__STDC__] (obstack_int_grow_fast): Fix misnamed
+       macro argument.
+       Reported by Matej Vela <vela@debian.org>.
+
+--- libc/malloc/obstack.h      29 Jun 2004 16:15:03 -0000      1.20
++++ libc/malloc/obstack.h      12 Sep 2005 19:56:23 -0000      1.21
+@@ -446,7 +447,7 @@ __extension__                                                              \
+   (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr))
+ # define obstack_int_grow_fast(h,aint)                                        \
+-  (((int *) ((h)->next_free += sizeof (int)))[-1] = (aptr))
++  (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint))
+ # define obstack_blank(h,length)                                      \
+ ( (h)->temp = (length),                                                       \
diff --git a/src/patches/glibc/glibc-ppc-assume.patch b/src/patches/glibc/glibc-ppc-assume.patch
new file mode 100644 (file)
index 0000000..cfad4c9
--- /dev/null
@@ -0,0 +1,18 @@
+--- libc/sysdeps/unix/sysv/linux/powerpc/kernel-features.h.jj  2003-01-30 05:24:37.000000000 -0500
++++ libc/sysdeps/unix/sysv/linux/powerpc/kernel-features.h     2003-09-23 18:28:07.000000000 -0400
+@@ -0,0 +1,15 @@
++/* In RHEL3, we can assume the shipped kernel, which is 2.4.21.  */
++#include_next <kernel-features.h>
++
++#if !defined __ASSUME_NEW_PRCTL_SYSCALL && defined __powerpc__
++# define __ASSUME_NEW_PRCTL_SYSCALL           1
++#endif
++
++#if !defined __ASSUME_FIXED_CLONE_SYSCALL && defined __powerpc__ \
++    && !defined __powerpc64__
++# define __ASSUME_FIXED_CLONE_SYSCALL         1
++#endif
++
++#if !defined __ASSUME_NEW_RT_SIGRETURN_SYSCALL && defined __powerpc64__
++# define __ASSUME_NEW_RT_SIGRETURN_SYSCALL    1
++#endif
diff --git a/src/patches/glibc/glibc-ppc-fegetround.patch b/src/patches/glibc/glibc-ppc-fegetround.patch
new file mode 100644 (file)
index 0000000..5d49427
--- /dev/null
@@ -0,0 +1,19 @@
+2006-02-03  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/powerpc/fpu/bits/fenvinline.h (fegetround): Make asm
+       volatile.
+
+--- libc/sysdeps/powerpc/fpu/bits/fenvinline.h 6 Jul 2001 04:56:02 -0000       1.3
++++ libc/sysdeps/powerpc/fpu/bits/fenvinline.h 3 Feb 2006 22:28:37 -0000       1.4
+@@ -22,8 +23,9 @@
+ /* Inline definition for fegetround.  */
+ # define fegetround() \
+   (__extension__  ({ int __fegetround_result;                               \
+-                   __asm__ ("mcrfs 7,7 ; mfcr %0"                           \
+-                           : "=r"(__fegetround_result) : : "cr7");          \
++                   __asm__ __volatile__                                     \
++                     ("mcrfs 7,7 ; mfcr %0"                                 \
++                      : "=r"(__fegetround_result) : : "cr7");               \
+                    __fegetround_result & 3; }))
+ /* The weird 'i#*X' constraints on the following suppress a gcc
diff --git a/src/patches/glibc/glibc-ppc-libSegFault.patch b/src/patches/glibc/glibc-ppc-libSegFault.patch
new file mode 100644 (file)
index 0000000..943712a
--- /dev/null
@@ -0,0 +1,49 @@
+2006-09-16  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/powerpc/powerpc32/register-dump.h (register_dump): Don't
+       write '\0' to the fd.
+       * sysdeps/mach/hurd/powerpc/register-dump.h (register_dump): Likewise.
+       * sysdeps/powerpc/powerpc64/register-dump.h (register_dump): Likewise.
+       Change regs to unsigned long pointer from unsigned int, fix fscr
+       offset.
+
+--- libc/sysdeps/powerpc/powerpc32/register-dump.h     5 Sep 2002 08:25:50 -0000       1.1
++++ libc/sysdeps/powerpc/powerpc32/register-dump.h     17 Sep 2006 15:53:05 -0000      1.2
+@@ -113,7 +113,7 @@ register_dump (int fd, struct sigcontext
+     }
+   /* Write the output.  */
+-  write (fd, buffer, sizeof(buffer));
++  write (fd, buffer, sizeof(buffer) - 1);
+ }
+--- libc/sysdeps/powerpc/powerpc64/register-dump.h     17 Sep 2002 23:50:02 -0000      1.1
++++ libc/sysdeps/powerpc/powerpc64/register-dump.h     17 Sep 2006 15:53:33 -0000      1.2
+@@ -34,7 +34,7 @@ gr16-19: 000000000000010% 00000000000001
+ gr20-23: 000000000000014% 000000000000015% 000000000000016% 000000000000017%\n\
+ gr24-27: 000000000000018% 000000000000019% 00000000000001a% 00000000000001b%\n\
+ gr28-31: 00000000000001c% 00000000000001d% 00000000000001e% 00000000000001f%\n\
+-fscr=0000071%\n\
++fscr=000000000000050%\n\
+ fp0-3:   000000000000030% 000000000000031% 000000000000032% 000000000000033%\n\
+ fp4-7:   000000000000034% 000000000000035% 000000000000036% 000000000000037%\n\
+ fp8-11:  000000000000038% 000000000000038% 00000000000003a% 00000000000003b%\n\
+@@ -104,7 +104,7 @@ register_dump (int fd, struct sigcontext
+   char buffer[sizeof(dumpform)];
+   char *bufferpos;
+   unsigned regno;
+-  unsigned *regs = (unsigned *)(ctx->regs);
++  unsigned long *regs = (unsigned long *)(ctx->regs);
+   memcpy(buffer, dumpform, sizeof(dumpform));
+@@ -117,7 +117,7 @@ register_dump (int fd, struct sigcontext
+     }
+   /* Write the output.  */
+-  write (fd, buffer, sizeof(buffer));
++  write (fd, buffer, sizeof(buffer) - 1);
+ }
diff --git a/src/patches/glibc/glibc-ppc-strncmp.patch b/src/patches/glibc/glibc-ppc-strncmp.patch
new file mode 100644 (file)
index 0000000..28b9dd9
--- /dev/null
@@ -0,0 +1,230 @@
+2005-11-17  Steven Munroe  <sjmunroe@us.ibm.com>
+
+       [BZ #1877]
+       * string/test-strncmp.c (do_test_limit): Handle zero length and
+       non-zero align values.
+       (test_main): Correct do_test_limit tests for 64-bit.
+
+2005-11-17  Steven Munroe  <sjmunroe@us.ibm.com>
+
+       [BZ #1877]
+       * string/test-strncmp.c (do_test_limit): New function.
+       (do_test) Add cast to eliminate compiler warnings.
+       (do_random_tests) Add cast to eliminate compiler warnings.
+       (test_main) Add do_test_limit tests.
+       * sysdeps/powerpc/powerpc32/strncmp.S: Test length before unaligned
+       load.
+       * sysdeps/powerpc/powerpc64/strncmp.S: Likewise.
+
+--- libc/string/test-strncmp.c 17 Apr 2003 17:37:24 -0000      1.5
++++ libc/string/test-strncmp.c 18 Nov 2005 00:11:55 -0000      1.7
+@@ -86,6 +86,65 @@ do_one_test (impl_t *impl, const char *s
+ }
+ static void
++do_test_limit (size_t align1, size_t align2, size_t len, size_t n, int max_char,
++       int exp_result)
++{
++  size_t i, align_n;
++  char *s1, *s2;
++
++  if (n == 0)
++    {
++      s1 = (char*)(buf1 + page_size);
++      s2 = (char*)(buf2 + page_size);
++      if (HP_TIMING_AVAIL)
++      printf ("Length %4zd/%4zd:", len, n);
++      
++      FOR_EACH_IMPL (impl, 0)
++      do_one_test (impl, s1, s2, n, 0);
++
++      if (HP_TIMING_AVAIL)
++      putchar ('\n');
++      
++      return;
++    }
++
++  align1 &= 15;
++  align2 &= 15;
++  align_n = (page_size - n) & 15;
++
++  s1 = (char*)(buf1 + page_size - n);
++  s2 = (char*)(buf2 + page_size - n);
++  
++  if (align1 < align_n)
++    s1 -= (align_n - align1);
++    
++  if (align2 < align_n)
++    s2 -= (align_n - align2);
++    
++  for (i = 0; i < n; i++)
++    s1[i] = s2[i] = 1 + 23 * i % max_char;
++
++  if (len < n)
++    {
++      s1[len] = 0;
++      s2[len] = 0;
++      if (exp_result < 0)
++      s2[len] = 32;
++      else if (exp_result > 0)
++      s1[len] = 64;
++    }
++
++  if (HP_TIMING_AVAIL)
++    printf ("Length %4zd/%4zd, alignment %2zd/%2zd:", len, n, align1, align2);
++
++  FOR_EACH_IMPL (impl, 0)
++    do_one_test (impl, s1, s2, n, exp_result);
++
++  if (HP_TIMING_AVAIL)
++    putchar ('\n');
++}
++
++static void
+ do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char,
+        int exp_result)
+ {
+@@ -103,8 +162,8 @@ do_test (size_t align1, size_t align2, s
+   if (align2 + n + 1 >= page_size)
+     return;
+-  s1 = buf1 + align1;
+-  s2 = buf2 + align2;
++  s1 = (char*)(buf1 + align1);
++  s2 = (char*)(buf2 + align2);
+   for (i = 0; i < n; i++)
+     s1[i] = s2[i] = 1 + 23 * i % max_char;
+@@ -124,7 +183,7 @@ do_test (size_t align1, size_t align2, s
+     printf ("Length %4zd/%4zd, alignment %2zd/%2zd:", len, n, align1, align2);
+   FOR_EACH_IMPL (impl, 0)
+-    do_one_test (impl, s1, s2, n, exp_result);
++    do_one_test (impl, (char*)s1, (char*)s2, n, exp_result);
+   if (HP_TIMING_AVAIL)
+     putchar ('\n');
+@@ -208,7 +267,7 @@ do_random_tests (void)
+       FOR_EACH_IMPL (impl, 1)
+       {
+-        r = CALL (impl, p1 + align1, p2 + align2, size);
++        r = CALL (impl, (char*)(p1 + align1), (char*)(p2 + align2), size);
+         /* Test whether on 64-bit architectures where ABI requires
+            callee to promote has the promotion been done.  */
+         asm ("" : "=g" (r) : "0" (r));
+@@ -271,6 +330,24 @@ test_main (void)
+       do_test (2 * i, i, 8 << i, 16 << i, 255, 0);
+       do_test (2 * i, i, 8 << i, 16 << i, 255, 1);
+     }
++    
++  do_test_limit (0, 0, 0, 0, 127, 0);
++  do_test_limit (4, 0, 21, 20, 127, 0);
++  do_test_limit (0, 4, 21, 20, 127, 0);
++  do_test_limit (8, 0, 25, 24, 127, 0);
++  do_test_limit (0, 8, 25, 24, 127, 0);
++
++  for (i = 0; i < 8; ++i)
++    {
++      do_test_limit (0, 0, 17 - i, 16 - i, 127, 0);
++      do_test_limit (0, 0, 17 - i, 16 - i, 255, 0);
++      do_test_limit (0, 0, 15 - i, 16 - i, 127, 0);
++      do_test_limit (0, 0, 15 - i, 16 - i, 127, 1);
++      do_test_limit (0, 0, 15 - i, 16 - i, 127, -1);
++      do_test_limit (0, 0, 15 - i, 16 - i, 255, 0);
++      do_test_limit (0, 0, 15 - i, 16 - i, 255, 1);
++      do_test_limit (0, 0, 15 - i, 16 - i, 255, -1);
++    }
+   do_random_tests ();
+   return ret;
+--- libc/sysdeps/powerpc/powerpc32/strncmp.S   3 Nov 2003 17:38:35 -0000       1.1
++++ libc/sysdeps/powerpc/powerpc32/strncmp.S   17 Nov 2005 21:14:37 -0000      1.2
+@@ -47,6 +47,7 @@ EALIGN (BP_SYM(strncmp), 4, 0)
+       lis     r7F7F, 0x7f7f
+       dcbt    0,rSTR2
+       clrlwi. rTMP, rTMP, 30
++      cmplwi  cr1, rN, 0
+       lis     rFEFE, -0x101
+       bne     L(unaligned)
+ /* We are word alligned so set up for two loops.  first a word
+@@ -54,7 +55,8 @@ EALIGN (BP_SYM(strncmp), 4, 0)
+       srwi.   rTMP, rN, 2
+       clrlwi  rN, rN, 30
+       addi    rFEFE, rFEFE, -0x101
+-      addi    r7F7F, r7F7F, 0x7f7f    
++      addi    r7F7F, r7F7F, 0x7f7f
++      cmplwi  cr1, rN, 0      
+       beq     L(unaligned)
+       mtctr   rTMP    /* Power4 wants mtctr 1st in dispatch group.  */
+@@ -122,16 +124,19 @@ L(tail):
+       addi    rSTR1, rSTR1, 4
+       bne-    cr1, L(different)
+       addi    rSTR2, rSTR2, 4
++      cmplwi  cr1, rN, 0
+ L(unaligned):
+       mtctr   rN      /* Power4 wants mtctr 1st in dispatch group */
+-      cmpwi   rN,0
+-      lbz     rWORD1, 0(rSTR1)
+-      lbz     rWORD2, 0(rSTR2)
+-      bgt     L(u1)
++      bgt     cr1, L(uz)
+ L(ux):
+       li      rRTN, 0
+       blr
+-
++      .align 4
++L(uz):
++      lbz     rWORD1, 0(rSTR1)
++      lbz     rWORD2, 0(rSTR2)
++      nop
++      b       L(u1)
+ L(u0):
+       lbzu    rWORD2, 1(rSTR2)
+ L(u1):
+--- libc/sysdeps/powerpc/powerpc64/strncmp.S   6 Oct 2004 22:08:54 -0000       1.2
++++ libc/sysdeps/powerpc/powerpc64/strncmp.S   17 Nov 2005 21:14:37 -0000      1.3
+@@ -48,6 +48,7 @@ EALIGN (BP_SYM(strncmp), 4, 0)
+       lis     r7F7F, 0x7f7f
+       dcbt    0,rSTR2
+       clrldi. rTMP, rTMP, 61
++      cmpldi  cr1, rN, 0
+       lis     rFEFE, -0x101
+       bne     L(unaligned)
+ /* We are doubleword alligned so set up for two loops.  first a double word
+@@ -55,7 +56,8 @@ EALIGN (BP_SYM(strncmp), 4, 0)
+       srdi.   rTMP, rN, 3
+       clrldi  rN, rN, 61
+       addi    rFEFE, rFEFE, -0x101
+-      addi    r7F7F, r7F7F, 0x7f7f    
++      addi    r7F7F, r7F7F, 0x7f7f
++      cmpldi  cr1, rN, 0      
+       beq     L(unaligned)
+       mtctr   rTMP    /* Power4 wants mtctr 1st in dispatch group.  */
+@@ -126,16 +128,19 @@ L(tail):
+       addi    rSTR1, rSTR1, 8
+       bne-    cr1, L(different)
+       addi    rSTR2, rSTR2, 8
++      cmpldi  cr1, rN, 0
+ L(unaligned):
+       mtctr   rN      /* Power4 wants mtctr 1st in dispatch group */
+-      cmpdi   rN,0
+-      lbz     rWORD1, 0(rSTR1)
+-      lbz     rWORD2, 0(rSTR2)
+-      bgt     L(u1)
++      bgt     cr1, L(uz)
+ L(ux):
+       li      rRTN, 0
+       blr
+-
++      .align 4
++L(uz):
++      lbz     rWORD1, 0(rSTR1)
++      lbz     rWORD2, 0(rSTR2)
++      nop
++      b       L(u1)
+ L(u0):
+       lbzu    rWORD2, 1(rSTR2)
+ L(u1):
diff --git a/src/patches/glibc/glibc-prelink-dynamic-weak.patch b/src/patches/glibc/glibc-prelink-dynamic-weak.patch
new file mode 100644 (file)
index 0000000..13c9490
--- /dev/null
@@ -0,0 +1,17 @@
+2006-10-02  Ulrich Drepper  <drepper@redhat.com>
+
+       * elf/rtld.c (dl_main): Don't use prelinking if LD_DYNAMIC_WEAK is
+       used.
+
+--- libc/elf/rtld.c    29 Sep 2006 16:56:15 -0000      1.363
++++ libc/elf/rtld.c    2 Oct 2006 18:24:37 -0000       1.364
+@@ -2087,7 +2087,8 @@ ERROR: ld.so: object '%s' cannot be load
+     }
+   if (main_map->l_info[ADDRIDX (DT_GNU_LIBLIST)]
+-      && ! __builtin_expect (GLRO(dl_profile) != NULL, 0))
++      && ! __builtin_expect (GLRO(dl_profile) != NULL, 0)
++      && ! __builtin_expect (GLRO(dl_dynamic_weak), 0))
+     {
+       ElfW(Lib) *liblist, *liblistend;
+       struct link_map **r_list, **r_listend, *l;
diff --git a/src/patches/glibc/glibc-printf-string-len.patch b/src/patches/glibc/glibc-printf-string-len.patch
new file mode 100644 (file)
index 0000000..b375df4
--- /dev/null
@@ -0,0 +1,22 @@
+2007-05-06  Ulrich Drepper  <drepper@redhat.com>
+
+       * stdio-common/vfprintf.c (process_string_arg): Optimize
+       ridiculous precision in wide char code printing multi-byte string.
+       Reported by Jim Meyering <jim@meyering.net>.
+
+--- libc/stdio-common/vfprintf.c       5 May 2007 04:41:35 -0000       1.138
++++ libc/stdio-common/vfprintf.c       7 May 2007 03:43:55 -0000       1.139
+@@ -1026,10 +1026,11 @@ vfprintf (FILE *s, const CHAR_T *format,
+           const char *mbs = (const char *) string;                          \
+           mbstate_t mbstate;                                                \
+                                                                             \
+-          len = prec != -1 ? (size_t) prec : strlen (mbs);                  \
++          len = prec != -1 ? __strnlen (mbs, (size_t) prec) : strlen (mbs); \
+                                                                             \
+           /* Allocate dynamically an array which definitely is long         \
+-             enough for the wide character version.  */                     \
++             enough for the wide character version.  Each byte in the       \
++             multi-byte string can produce at most one wide character.  */  \
+           if (__libc_use_alloca (len * sizeof (wchar_t)))                   \
+             string = (CHAR_T *) alloca (len * sizeof (wchar_t));            \
+           else if ((string = (CHAR_T *) malloc (len * sizeof (wchar_t)))    \
diff --git a/src/patches/glibc/glibc-pthread_getattr_np.patch b/src/patches/glibc/glibc-pthread_getattr_np.patch
new file mode 100644 (file)
index 0000000..2ec5ad5
--- /dev/null
@@ -0,0 +1,22 @@
+2007-06-22  Jakub Jelinek  <jakub@redhat.com>
+
+       * pthread_getattr_np.c (pthread_getattr_np): Clear cpuset and
+       cpusetsize if pthread_getaffinity_np failed with ENOSYS.
+
+--- libc/nptl/pthread_getattr_np.c     30 May 2007 04:42:57 -0000      1.13
++++ libc/nptl/pthread_getattr_np.c     22 Jun 2007 22:13:52 -0000      1.14
+@@ -164,8 +164,12 @@ pthread_getattr_np (thread_id, attr)
+       {
+         free (cpuset);
+         if (ret == ENOSYS)
+-          /* There is no such functionality.  */
+-          ret = 0;
++          {     
++            /* There is no such functionality.  */
++            ret = 0;
++            iattr->cpuset = NULL;
++            iattr->cpusetsize = 0;
++          }
+       }
+     }
diff --git a/src/patches/glibc/glibc-quota_h.patch b/src/patches/glibc/glibc-quota_h.patch
new file mode 100644 (file)
index 0000000..9f312a3
--- /dev/null
@@ -0,0 +1,16 @@
+--- libc/sysdeps/unix/sysv/linux/sys/quota.h   2005-10-17 10:03:21.000000000 +0200
++++ libc/sysdeps/unix/sysv/linux/sys/quota.h   2005-11-17 11:39:51.000000000 +0100
+@@ -42,10 +42,10 @@
+ /*
+  * Select between different incompatible quota versions.
+- * Default to the version used by Linux kernel version 2.4.22
+- * or later.  */
++ * Default to the version used by Linux kernel version 2.4.21
++ * or earlier (in RHEL version 1 is AS2.1, version 2 is RHEL3 and later).  */
+ #ifndef _LINUX_QUOTA_VERSION
+-# define _LINUX_QUOTA_VERSION 2
++# define _LINUX_QUOTA_VERSION 1
+ #endif
+ /*
diff --git a/src/patches/glibc/glibc-readonly-area.patch b/src/patches/glibc/glibc-readonly-area.patch
new file mode 100644 (file)
index 0000000..b8857f4
--- /dev/null
@@ -0,0 +1,44 @@
+2005-10-17  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/unix/sysv/linux/readonly-area.c (__readonly_area): Also
+       allow EACCES errors when opening /proc for now.
+
+2005-10-06  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/unix/sysv/linux/readonly-area.c: Allow fopen to fail because
+       the file does not exist.
+
+--- libc/sysdeps/unix/sysv/linux/readonly-area.c       2004/10/18 04:17:11     1.1
++++ libc/sysdeps/unix/sysv/linux/readonly-area.c       2005/10/17 15:51:01     1.4
+@@ -16,6 +16,7 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
++#include <errno.h>
+ #include <stdint.h>
+ #include <stdio.h>
+ #include <stdio_ext.h>
+@@ -33,10 +34,19 @@
+   FILE *fp = fopen ("/proc/self/maps", "rc");
+   if (fp == NULL)
+-    /* We don't know.  Returning 1 here means that programs using %n
+-       and -D_FORTIFY_SOURCE=2 will work even when /proc is not mounted,
+-       but will allow %n even in writable areas.  */
+-    return 1;
++    {
++      /* It is the system administrator's choice to not have /proc
++       available to this process (e.g., because it runs in a chroot
++       environment.  Don't fail in this case.  */
++      if (errno == ENOENT
++        /* The kernel has a bug in that a process is denied access
++           to the /proc filesystem if it is set[ug]id.  There has
++           been no willingness to change this in the kernel so
++           far.  */
++        || errno == EACCES)
++      return 1;
++      return -1;
++    }
+   /* We need no locking.  */
+   __fsetlocking (fp, FSETLOCKING_BYCALLER);
diff --git a/src/patches/glibc/glibc-regex_h-STDC.patch b/src/patches/glibc/glibc-regex_h-STDC.patch
new file mode 100644 (file)
index 0000000..a497ca7
--- /dev/null
@@ -0,0 +1,221 @@
+2005-09-06  Ulrich Drepper  <drepper@redhat.com>
+
+       * include/regex.h: Remove use of _RE_ARGS.
+
+2005-08-20  Paul Eggert  <eggert@cs.ucla.edu>
+
+       * posix/regex.h (_RE_ARGS): Remove.  No longer needed, since we assume
+       C89 or better.  All uses removed.
+
+--- libc/posix/regex.h 18 Aug 2005 06:42:25 -0000      1.34
++++ libc/posix/regex.h 6 Sep 2005 18:17:56 -0000       1.35
+@@ -452,38 +452,21 @@ typedef struct
\f
+ /* Declarations for routines.  */
+-/* To avoid duplicating every routine declaration -- once with a
+-   prototype (if we are ANSI), and once without (if we aren't) -- we
+-   use the following macro to declare argument types.  This
+-   unfortunately clutters up the declarations a bit, but I think it's
+-   worth it.  */
+-
+-#if __STDC__
+-
+-# define _RE_ARGS(args) args
+-
+-#else /* not __STDC__ */
+-
+-# define _RE_ARGS(args) ()
+-
+-#endif /* not __STDC__ */
+-
+ /* Sets the current default syntax to SYNTAX, and return the old syntax.
+    You can also simply assign to the `re_syntax_options' variable.  */
+-extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
++extern reg_syntax_t re_set_syntax (reg_syntax_t syntax);
+ /* Compile the regular expression PATTERN, with length LENGTH
+    and syntax given by the global `re_syntax_options', into the buffer
+    BUFFER.  Return NULL if successful, and an error string if not.  */
+-extern const char *re_compile_pattern
+-  _RE_ARGS ((const char *pattern, size_t length,
+-             struct re_pattern_buffer *buffer));
++extern const char *re_compile_pattern (const char *pattern, size_t length,
++                                     struct re_pattern_buffer *buffer);
+ /* Compile a fastmap for the compiled pattern in BUFFER; used to
+    accelerate searches.  Return 0 if successful and -2 if was an
+    internal error.  */
+-extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
++extern int re_compile_fastmap (struct re_pattern_buffer *buffer);
+ /* Search in the string STRING (with length LENGTH) for the pattern
+@@ -491,31 +474,29 @@ extern int re_compile_fastmap _RE_ARGS (
+    characters.  Return the starting position of the match, -1 for no
+    match, or -2 for an internal error.  Also return register
+    information in REGS (if REGS and BUFFER->no_sub are nonzero).  */
+-extern int re_search
+-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+-            int length, int start, int range, struct re_registers *regs));
++extern int re_search (struct re_pattern_buffer *buffer, const char *string,
++                    int length, int start, int range,
++                    struct re_registers *regs);
+ /* Like `re_search', but search in the concatenation of STRING1 and
+    STRING2.  Also, stop searching at index START + STOP.  */
+-extern int re_search_2
+-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+-             int length1, const char *string2, int length2,
+-             int start, int range, struct re_registers *regs, int stop));
++extern int re_search_2 (struct re_pattern_buffer *buffer, const char *string1,
++                      int length1, const char *string2, int length2,
++                      int start, int range, struct re_registers *regs,
++                      int stop);
+ /* Like `re_search', but return how many characters in STRING the regexp
+    in BUFFER matched, starting at position START.  */
+-extern int re_match
+-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+-             int length, int start, struct re_registers *regs));
++extern int re_match (struct re_pattern_buffer *buffer, const char *string,
++                   int length, int start, struct re_registers *regs);
+ /* Relates to `re_match' as `re_search_2' relates to `re_search'.  */
+-extern int re_match_2
+-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+-             int length1, const char *string2, int length2,
+-             int start, struct re_registers *regs, int stop));
++extern int re_match_2 (struct re_pattern_buffer *buffer, const char *string1,
++                     int length1, const char *string2, int length2,
++                     int start, struct re_registers *regs, int stop);
+ /* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+@@ -530,15 +511,15 @@ extern int re_match_2
+    Unless this function is called, the first search or match using
+    PATTERN_BUFFER will allocate its own register data, without
+    freeing the old data.  */
+-extern void re_set_registers
+-  _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
+-             unsigned num_regs, regoff_t *starts, regoff_t *ends));
++extern void re_set_registers (struct re_pattern_buffer *buffer,
++                            struct re_registers *regs, unsigned num_regs,
++                            regoff_t *starts, regoff_t *ends);
+ #if defined _REGEX_RE_COMP || defined _LIBC
+ # ifndef _CRAY
+ /* 4.2 bsd compatibility.  */
+-extern char *re_comp _RE_ARGS ((const char *));
+-extern int re_exec _RE_ARGS ((const char *));
++extern char *re_comp (const char *);
++extern int re_exec (const char *);
+ # endif
+ #endif
+@@ -563,19 +544,19 @@ extern int re_exec _RE_ARGS ((const char
+ #endif
+ /* POSIX compatibility.  */
+-extern int regcomp _RE_ARGS ((regex_t *__restrict __preg,
+-                            const char *__restrict __pattern,
+-                            int __cflags));
+-
+-extern int regexec _RE_ARGS ((const regex_t *__restrict __preg,
+-                            const char *__restrict __string, size_t __nmatch,
+-                            regmatch_t __pmatch[__restrict_arr],
+-                            int __eflags));
++extern int regcomp (regex_t *__restrict __preg,
++                  const char *__restrict __pattern,
++                  int __cflags);
++
++extern int regexec (const regex_t *__restrict __preg,
++                  const char *__restrict __string, size_t __nmatch,
++                  regmatch_t __pmatch[__restrict_arr],
++                  int __eflags);
+-extern size_t regerror _RE_ARGS ((int __errcode, const regex_t *__preg,
+-                                char *__errbuf, size_t __errbuf_size));
++extern size_t regerror (int __errcode, const regex_t *__preg,
++                      char *__errbuf, size_t __errbuf_size);
+-extern void regfree _RE_ARGS ((regex_t *__preg));
++extern void regfree (regex_t *__preg);
+ #ifdef __cplusplus
+--- libc/include/regex.h       8 Dec 1998 13:10:59 -0000       1.2
++++ libc/include/regex.h       6 Sep 2005 20:37:50 -0000       1.3
+@@ -2,45 +2,42 @@
+ #include <posix/regex.h>
+ /* Document internal interfaces.  */
+-extern reg_syntax_t __re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
++extern reg_syntax_t __re_set_syntax (reg_syntax_t syntax);
+-extern const char *__re_compile_pattern
+-  _RE_ARGS ((const char *pattern, size_t length,
+-             struct re_pattern_buffer *buffer));
++extern const char *__re_compile_pattern (const char *pattern, size_t length,
++                                       struct re_pattern_buffer *buffer);
+-extern int __re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
++extern int __re_compile_fastmap (struct re_pattern_buffer *buffer);
+-extern int __re_search
+-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+-            int length, int start, int range, struct re_registers *regs));
++extern int __re_search (struct re_pattern_buffer *buffer, const char *string,
++                      int length, int start, int range,
++                      struct re_registers *regs);
+ extern int __re_search_2
+-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+-             int length1, const char *string2, int length2,
+-             int start, int range, struct re_registers *regs, int stop));
++  (struct re_pattern_buffer *buffer, const char *string1,
++   int length1, const char *string2, int length2,
++   int start, int range, struct re_registers *regs, int stop);
+ extern int __re_match
+-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+-             int length, int start, struct re_registers *regs));
++  (struct re_pattern_buffer *buffer, const char *string,
++   int length, int start, struct re_registers *regs);
+ extern int __re_match_2
+-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+-             int length1, const char *string2, int length2,
+-             int start, struct re_registers *regs, int stop));
++  (struct re_pattern_buffer *buffer, const char *string1,
++   int length1, const char *string2, int length2,
++   int start, struct re_registers *regs, int stop);
+ extern void __re_set_registers
+-  _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
+-             unsigned num_regs, regoff_t *starts, regoff_t *ends));
++  (struct re_pattern_buffer *buffer, struct re_registers *regs,
++   unsigned num_regs, regoff_t *starts, regoff_t *ends);
+-extern int __regcomp _RE_ARGS ((regex_t *__preg, const char *__pattern,
+-                              int __cflags));
++extern int __regcomp (regex_t *__preg, const char *__pattern, int __cflags);
+-extern int __regexec _RE_ARGS ((const regex_t *__preg,
+-                              const char *__string, size_t __nmatch,
+-                              regmatch_t __pmatch[], int __eflags));
++extern int __regexec (const regex_t *__preg, const char *__string,
++                    size_t __nmatch, regmatch_t __pmatch[], int __eflags);
+-extern size_t __regerror _RE_ARGS ((int __errcode, const regex_t *__preg,
+-                                  char *__errbuf, size_t __errbuf_size));
++extern size_t __regerror (int __errcode, const regex_t *__preg,
++                        char *__errbuf, size_t __errbuf_size);
+-extern void __regfree _RE_ARGS ((regex_t *__preg));
++extern void __regfree (regex_t *__preg);
+ #endif
diff --git a/src/patches/glibc/glibc-resolv-send_vc.patch b/src/patches/glibc/glibc-resolv-send_vc.patch
new file mode 100644 (file)
index 0000000..4f2b118
--- /dev/null
@@ -0,0 +1,17 @@
+2005-08-21  Ulrich Drepper  <drepper@redhat.com>
+
+       * resolv/res_send.c (send_vc): Pass correct sockaddr size to connect.
+
+--- libc/resolv/res_send.c     8 Jul 2005 06:49:08 -0000       1.42
++++ libc/resolv/res_send.c     21 Aug 2005 23:07:10 -0000      1.43
+@@ -654,7 +654,9 @@ send_vc(res_state statp,
+               }
+               __set_errno (0);
+               if (connect(statp->_vcsock, (struct sockaddr *)nsap,
+-                          sizeof *nsap) < 0) {
++                          nsap->sin6_family == AF_INET
++                          ? sizeof (struct sockaddr_in)
++                          : sizeof (struct sockaddr_in6)) < 0) {
+                       *terrno = errno;
+                       Aerror(statp, stderr, "connect/vc", errno,
+                              (struct sockaddr *) nsap);
diff --git a/src/patches/glibc/glibc-rh168266.patch b/src/patches/glibc/glibc-rh168266.patch
new file mode 100644 (file)
index 0000000..11f657d
--- /dev/null
@@ -0,0 +1,246 @@
+2006-02-28  Roland McGrath  <roland@redhat.com>
+
+       * libio/genops.c: Include <sched.h> for __sched_yield decl.
+
+2006-02-23  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/generic/sched_yield.c (__sched_yield): Add libc_hidden_def.
+       * sysdeps/mach/sched_yield.c (__sched_yield): Likewise.
+
+2006-01-14  Jakub Jelinek  <jakub@redhat.com>
+
+       * libio/libio.h (_IO_vfscanf, _IO_vfprintf): Remove __THROW.
+       (_IO_vfwscanf, _IO_vfwprintf): Likewise.
+       * libio/libioP.h (_IO_vdprintf): Likewise.
+
+2006-01-11  Ulrich Drepper  <drepper@redhat.com>
+
+       * libio/memstream.c (_IO_mem_finish): Fix potential memory leak if
+       realloc fails.
+
+       * include/sched.h: Add libc_hidden_proto for __sched_yield.
+
+       * libio/genops.c (_IO_unbuffer_write): Give concurrently running
+       threads the chance to work correctly by trying to lock the stream.
+       If this does not work, proceed without locking.
+
+2006-01-10  Ulrich Drepper  <drepper@redhat.com>
+
+       * libio/genops.c (_IO_unbuffer_write): Don't always free the
+       buffer.  This is not necessary except in debug mode.  If we don't
+       free the buffer but the FILE structure to a list.
+       (buffer_free): New function.  Free buffers or tell _IO_unbuffer_write
+       to do so.
+       * libio/libio.h (struct _IO_FILE): Add new members to keep track
+        of which buffers have to be freed.
+
+--- libc/libio/genops.c        14 Sep 2004 04:24:44 -0000
++++ libc/libio/genops.c        11 Jan 2006 08:09:39 -0000
+@@ -34,5 +34,8 @@
+ #endif
+ #include <string.h>
++#ifdef _LIBC
++#include <sched.h>
++#endif
+ #ifdef _IO_MTSAFE_IO
+ static _IO_lock_t list_all_lock = _IO_lock_initializer;
+@@ -657,6 +658,7 @@ _IO_no_init (fp, flags, orientation, wd,
+       fp->_wide_data->_wide_vtable = jmp;
+     }
+ #endif
++  fp->_freeres_list = NULL;
+ }
+ int
+@@ -914,10 +916,27 @@ INTDEF(_IO_flush_all_linebuffered)
+ weak_alias (_IO_flush_all_linebuffered, _flushlbf)
+ #endif
++
++/* The following is a bit tricky.  In general, we want to unbuffer the
++   streams so that all output which follows is seen.  If we are not
++   looking for memory leaks it does not make much sense to free the
++   actual buffer because this will happen anyway once the program
++   terminated.  If we do want to look for memory leaks we have to free
++   the buffers.  Whether something is freed is determined by the
++   function sin the libc_freeres section.  Those are called as part of
++   the atexit routine, just like _IO_cleanup.  The problem is we do
++   not know whether the freeres code is called first or _IO_cleanup.
++   if the former is the case, we set the DEALLOC_BUFFER variable to
++   true and _IO_unbuffer_write will take care of the rest.  If
++   _IO_unbuffer_write is called first we add the streams to a list
++   which the freeres function later can walk through.  */
+ static void _IO_unbuffer_write (void);
++static bool dealloc_buffers;
++static _IO_FILE *freeres_list;
++
+ static void
+-_IO_unbuffer_write ()
++_IO_unbuffer_write (void)
+ {
+   struct _IO_FILE *fp;
+   for (fp = (_IO_FILE *) INTUSE(_IO_list_all); fp; fp = fp->_chain)
+@@ -927,7 +946,32 @@ _IO_unbuffer_write ()
+             || (fp->_flags & _IO_IS_APPENDING))
+         /* Iff stream is un-orientated, it wasn't used. */
+         && fp->_mode != 0)
+-      _IO_SETBUF (fp, NULL, 0);
++      {
++        int cnt;
++#define MAXTRIES 2
++        for (cnt = 0; cnt < MAXTRIES; ++cnt)
++          if (_IO_lock_trylock (*fp->_lock) == 0)
++            break;
++          else
++            /* Give the other thread time to finish up its use of the
++               stream.  */
++            __sched_yield ();
++
++        if (! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
++          {
++            fp->_flags |= _IO_USER_BUF;
++
++            fp->_freeres_list = freeres_list;
++            freeres_list = fp;
++            fp->_freeres_buf = fp->_IO_buf_base;
++            fp->_freeres_size = _IO_blen (fp);
++          }
++
++        _IO_SETBUF (fp, NULL, 0);
++
++        if (cnt < MAXTRIES)
++          _IO_lock_unlock (*fp->_lock);
++      }
+       /* Make sure that never again the wide char functions can be
+        used.  */
+@@ -935,11 +979,25 @@ _IO_unbuffer_write ()
+     }
+ }
++
++libc_freeres_fn (buffer_free)
++{
++  dealloc_buffers = true;
++
++  while (freeres_list != NULL)
++    {
++      FREE_BUF (freeres_list->_freeres_buf, freeres_list->_freeres_size);
++
++      freeres_list = freeres_list->_freeres_list;
++    }
++}
++
++
+ int
+ _IO_cleanup ()
+ {
+   /* We do *not* want locking.  Some threads might use streams but
+-     that is there problem, we flush them underneath them.  */
++     that is their problem, we flush them underneath them.  */
+   int result = _IO_flush_all_lockp (0);
+   /* We currently don't have a reliable mechanism for making sure that
+--- libc/libio/libio.h 17 Feb 2005 01:16:15 -0000      1.61
++++ libc/libio/libio.h 11 Jan 2006 07:47:46 -0000      1.63
+@@ -317,13 +317,19 @@ struct _IO_FILE_complete
+   /* Wide character stream stuff.  */
+   struct _IO_codecvt *_codecvt;
+   struct _IO_wide_data *_wide_data;
++  struct _IO_FILE *_freeres_list;
++  void *_freeres_buf;
++  size_t _freeres_size;
+ # else
+   void *__pad1;
+   void *__pad2;
++  void *__pad3;
++  void *__pad4;
++  size_t __pad5;
+ # endif
+   int _mode;
+   /* Make sure we don't get into trouble again.  */
+-  char _unused2[15 * sizeof (int) - 2 * sizeof (void *)];
++  char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
+ #endif
+ };
+@@ -472,9 +478,9 @@ extern int _IO_ftrylockfile (_IO_FILE *)
+ #endif /* !_IO_MTSAFE_IO */
+ extern int _IO_vfscanf (_IO_FILE * __restrict, const char * __restrict,
+-                      _IO_va_list, int *__restrict) __THROW;
++                      _IO_va_list, int *__restrict);
+ extern int _IO_vfprintf (_IO_FILE *__restrict, const char *__restrict,
+-                       _IO_va_list) __THROW;
++                       _IO_va_list);
+ extern _IO_ssize_t _IO_padn (_IO_FILE *, int, _IO_ssize_t) __THROW;
+ extern _IO_size_t _IO_sgetn (_IO_FILE *, void *, _IO_size_t) __THROW;
+@@ -521,8 +527,8 @@ weak_extern (_IO_stdin_used);
+ # endif
+ extern int _IO_vfwscanf (_IO_FILE * __restrict, const wchar_t * __restrict,
+-                       _IO_va_list, int *__restrict) __THROW;
++                       _IO_va_list, int *__restrict);
+ extern int _IO_vfwprintf (_IO_FILE *__restrict, const wchar_t *__restrict,
+-                        _IO_va_list) __THROW;
++                        _IO_va_list);
+ extern _IO_ssize_t _IO_wpadn (_IO_FILE *, wint_t, _IO_ssize_t) __THROW;
+ extern void _IO_free_wbackup_area (_IO_FILE *) __THROW;
+ #endif
+--- libc/libio/memstream.c     14 Sep 2004 04:24:45 -0000      1.23
++++ libc/libio/memstream.c     11 Jan 2006 17:46:36 -0000      1.24
+@@ -140,9 +140,9 @@ _IO_mem_finish (fp, dummy)
+     {
+       (*mp->bufloc)[fp->_IO_write_ptr - fp->_IO_write_base] = '\0';
+       *mp->sizeloc = fp->_IO_write_ptr - fp->_IO_write_base;
+-    }
+-  fp->_IO_buf_base = NULL;
++      fp->_IO_buf_base = NULL;
++    }
+-  INTUSE(_IO_default_finish) (fp, 0);
++  _IO_str_finish (fp, 0);
+ }
+--- libc/libio/libioP.h        19 Dec 2005 03:32:08 -0000      1.74
++++ libc/libio/libioP.h        14 Jan 2006 12:09:46 -0000      1.75
+@@ -649,7 +652,7 @@ extern void _IO_wstr_finish (_IO_FILE *,
+ extern int _IO_vasprintf (char **result_ptr, __const char *format,
+                         _IO_va_list args) __THROW;
+-extern int _IO_vdprintf (int d, __const char *format, _IO_va_list arg) __THROW;
++extern int _IO_vdprintf (int d, __const char *format, _IO_va_list arg);
+ extern int _IO_vsnprintf (char *string, _IO_size_t maxlen,
+                         __const char *format, _IO_va_list args) __THROW;
+--- libc/include/sched.h       3 Mar 2003 21:32:45 -0000       1.11
++++ libc/include/sched.h       11 Jan 2006 17:45:18 -0000      1.12
+@@ -10,6 +10,7 @@ extern int __sched_setscheduler (__pid_t
+ libc_hidden_proto (__sched_setscheduler)
+ extern int __sched_getscheduler (__pid_t __pid);
+ extern int __sched_yield (void);
++libc_hidden_proto (__sched_yield)
+ extern int __sched_get_priority_max (int __algorithm);
+ extern int __sched_get_priority_min (int __algorithm);
+ extern int __sched_rr_get_interval (__pid_t __pid, struct timespec *__t);
+--- libc/sysdeps/generic/sched_yield.c 14 Dec 2005 10:39:15 -0000      1.1
++++ libc/sysdeps/generic/sched_yield.c 23 Feb 2006 22:32:34 -0000      1.2
+@@ -28,6 +28,7 @@ __sched_yield (void)
+   return -1;
+ }
+ stub_warning (sched_yield)
++libc_hidden_def (__sched_yield)
+ weak_alias (__sched_yield, sched_yield)
+ #include <stub-tag.h>
+--- libc/sysdeps/mach/sched_yield.c    6 Jul 2001 04:55:56 -0000       1.2
++++ libc/sysdeps/mach/sched_yield.c    23 Feb 2006 22:32:37 -0000      1.3
+@@ -28,4 +28,5 @@ __sched_yield (void)
+   (void) __swtch ();
+   return 0;
+ }
++libc_hidden_def (__sched_yield)
+ weak_alias (__sched_yield, sched_yield)
diff --git a/src/patches/glibc/glibc-rh178934.patch b/src/patches/glibc/glibc-rh178934.patch
new file mode 100644 (file)
index 0000000..95908f7
--- /dev/null
@@ -0,0 +1,337 @@
+2007-03-22  Jakub Jelinek  <jakub@redhat.com>
+
+       * config.h.in (HAVE_LIBCAP): Add.
+       * nscd/selinux.h: Include sys/capability.h rather than non-existent
+       sys/capabilities.h.
+       * nscd/selinux.c (preserve_capabilities): Use cap_free instead of
+       free_caps.  Cast away const from 4th cap_set_flag argument.
+
+2006-04-26  James Antill  <james.antill@redhat.com>
+           Ulrich Drepper  <drepper@redhat.com>
+
+       * config.make.in: Add have-libcap.
+       * configure.in: Check for libcap.
+       * nscd/Makefile (selinux-LIBS): Add -lcap if possible.
+       * nscd/connections.c (finish_drop_privileges): When libcap is available
+       call preserve_capabilities and install_real_capabilities.
+       * nscd/selinux.c: Define preserve_capabilities and
+       install_real_capabilities.
+       * nscd/selinux.h: Declare preserve_capabilities and
+       install_real_capabilities.
+
+--- libc/configure.in  1 Mar 2006 09:17:40 -0000       1.459
++++ libc/configure.in  26 Apr 2006 16:23:49 -0000      1.460
+@@ -1982,6 +1982,13 @@ if test "x$have_selinux" = xyes; then
+     AC_DEFINE(HAVE_LIBAUDIT, 1, [SELinux libaudit support])
+   fi
+   AC_SUBST(have_libaudit)
++
++  # See if we have the libcap library
++  AC_CHECK_LIB(cap, cap_init, have_libcap=yes, have_libcap=no)
++  if test "x$have_libcap" = xyes; then
++    AC_DEFINE(HAVE_LIBCAP, 1, [SELinux libcap support])
++  fi
++  AC_SUBST(have_libcap)
+ fi
+ AC_SUBST(have_selinux)
+--- libc/config.make.in        28 Feb 2006 07:05:38 -0000      1.117
++++ libc/config.make.in        26 Apr 2006 16:22:38 -0000      1.118
+@@ -61,6 +61,7 @@ have-fpie = @libc_cv_fpie@
+ have-ssp = @libc_cv_ssp@
+ have-selinux = @have_selinux@
+ have-libaudit = @have_libaudit@
++have-libcap = @have_libcap@
+ have-cc-with-libunwind = @libc_cv_cc_with_libunwind@
+ fno-unit-at-a-time = @fno_unit_at_a_time@
+ bind-now = @bindnow@
+--- libc/configure     1 Mar 2006 09:17:40 -0000       1.449
++++ libc/configure     26 Apr 2006 16:13:55 -0000      1.450
+@@ -313,7 +313,7 @@ ac_includes_default="\
+ # include <unistd.h>
+ #endif"
+-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS with_fp with_cvs enable_check_abi oldest_abi bindnow force_install all_warnings build build_cpu build_vendor build_os host host_cpu host_vendor host_os subdirs add_ons base_machine sysnames INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC OBJEXT BUILD_CC cross_compiling CPP CXX CXXFLAGS ac_ct_CXX AR OBJDUMP RANLIB ac_ct_RANLIB MIG AS LD PWD_P MAKE MSGFMT MAKEINFO SED AUTOCONF SYSINCLUDES libc_cv_gcc_static_libgcc BASH libc_cv_have_bash2 KSH libc_cv_have_ksh AWK PERL INSTALL_INFO BISON VERSIONING libc_cv_asm_protected_directive libc_cv_initfinit_array libc_cv_cc_with_libunwind libc_cv_z_nodelete libc_cv_z_nodlopen libc_cv_z_initfirst libc_cv_z_relro libc_cv_Bgroup libc_cv_libgcc_s_suffix libc_cv_as_needed ASFLAGS_config libc_cv_z_combreloc libc_cv_z_execstack libc_cv_fpie fno_unit_at_a_time libc_cv_have_initfini libc_cv_cpp_asm_debuginfo no_whole_archive exceptions LIBGD have_libaudit have_selinux EGREP sizeof_long_double libc_cv_gcc_unwind_find_fde uname_sysname uname_release uname_version old_glibc_headers libc_cv_slibdir libc_cv_localedir libc_cv_sysconfdir libc_cv_rootsbindir libc_cv_forced_unwind use_ldconfig ldd_rewrite_script gnu_ld gnu_as elf xcoff static shared pic_default profile omitfp bounded static_nss nopic_initfini DEFINES linux_doors mach_interface_list VERSION RELEASE LIBOBJS LTLIBOBJS'
++ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS with_fp with_cvs enable_check_abi oldest_abi bindnow force_install all_warnings build build_cpu build_vendor build_os host host_cpu host_vendor host_os subdirs add_ons base_machine sysnames INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC OBJEXT BUILD_CC cross_compiling CPP CXX CXXFLAGS ac_ct_CXX AR OBJDUMP RANLIB ac_ct_RANLIB MIG AS LD PWD_P MAKE MSGFMT MAKEINFO SED AUTOCONF SYSINCLUDES libc_cv_gcc_static_libgcc BASH libc_cv_have_bash2 KSH libc_cv_have_ksh AWK PERL INSTALL_INFO BISON VERSIONING libc_cv_asm_protected_directive libc_cv_initfinit_array libc_cv_cc_with_libunwind libc_cv_z_nodelete libc_cv_z_nodlopen libc_cv_z_initfirst libc_cv_z_relro libc_cv_Bgroup libc_cv_libgcc_s_suffix libc_cv_as_needed ASFLAGS_config libc_cv_z_combreloc libc_cv_z_execstack libc_cv_fpie fno_unit_at_a_time libc_cv_have_initfini libc_cv_cpp_asm_debuginfo no_whole_archive exceptions LIBGD have_libaudit have_libcap have_selinux EGREP sizeof_long_double libc_cv_gcc_unwind_find_fde uname_sysname uname_release uname_version old_glibc_headers libc_cv_slibdir libc_cv_localedir libc_cv_sysconfdir libc_cv_rootsbindir libc_cv_forced_unwind use_ldconfig ldd_rewrite_script gnu_ld gnu_as elf xcoff static shared pic_default profile omitfp bounded static_nss nopic_initfini DEFINES linux_doors mach_interface_list VERSION RELEASE LIBOBJS LTLIBOBJS'
+ ac_subst_files=''
+ # Initialize some variables set by options.
+@@ -6855,6 +6855,86 @@ _ACEOF
+   fi
++
++  # See if we have the libcap library
++  echo "$as_me:$LINENO: checking for cap_init in -lcap" >&5
++echo $ECHO_N "checking for cap_init in -lcap... $ECHO_C" >&6
++if test "${ac_cv_lib_cap_cap_init+set}" = set; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++  ac_check_lib_save_LIBS=$LIBS
++LIBS="-lcap  $LIBS"
++cat >conftest.$ac_ext <<_ACEOF
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
++
++/* Override any gcc2 internal prototype to avoid an error.  */
++#ifdef __cplusplus
++extern "C"
++#endif
++/* We use char because int might match the return type of a gcc2
++   builtin and then its argument prototype would still apply.  */
++char cap_init ();
++int
++main ()
++{
++cap_init ();
++  ;
++  return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext conftest$ac_exeext
++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++  (eval $ac_link) 2>conftest.er1
++  ac_status=$?
++  grep -v '^ *+' conftest.er1 >conftest.err
++  rm -f conftest.er1
++  cat conftest.err >&5
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); } &&
++       { ac_try='test -z "$ac_c_werror_flag"
++                       || test ! -s conftest.err'
++  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++  (eval $ac_try) 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; } &&
++       { ac_try='test -s conftest$ac_exeext'
++  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++  (eval $ac_try) 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; }; then
++  ac_cv_lib_cap_cap_init=yes
++else
++  echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_cv_lib_cap_cap_init=no
++fi
++rm -f conftest.err conftest.$ac_objext \
++      conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++echo "$as_me:$LINENO: result: $ac_cv_lib_cap_cap_init" >&5
++echo "${ECHO_T}$ac_cv_lib_cap_cap_init" >&6
++if test $ac_cv_lib_cap_cap_init = yes; then
++  have_libcap=yes
++else
++  have_libcap=no
++fi
++
++  if test "x$have_libcap" = xyes; then
++
++cat >>confdefs.h <<\_ACEOF
++#define HAVE_LIBCAP 1
++_ACEOF
++
++  fi
++
+ fi
+@@ -8475,6 +8555,7 @@ s,@no_whole_archive@,$no_whole_archive,;
+ s,@exceptions@,$exceptions,;t t
+ s,@LIBGD@,$LIBGD,;t t
+ s,@have_libaudit@,$have_libaudit,;t t
++s,@have_libcap@,$have_libcap,;t t
+ s,@have_selinux@,$have_selinux,;t t
+ s,@EGREP@,$EGREP,;t t
+ s,@sizeof_long_double@,$sizeof_long_double,;t t
+--- libc/nscd/Makefile 4 Apr 2006 07:32:46 -0000       1.49
++++ libc/nscd/Makefile 26 Apr 2006 16:24:22 -0000      1.50
+@@ -55,10 +55,13 @@ all-nscd-modules := $(nscd-modules) seli
+ ifeq (yes,$(have-selinux))
+ ifeq (yes,$(have-libaudit))
+ libaudit = -laudit
++ifeq (yes,$(have-libcap))
++libcap = -lcap
++endif
+ endif
+ nscd-modules += selinux
+-selinux-LIBS := -lselinux $(libaudit)
++selinux-LIBS := -lselinux $(libaudit) $(libcap)
+ endif
+ LDLIBS-nscd = $(selinux-LIBS)
+--- libc/nscd/connections.c    1 Apr 2006 18:49:53 -0000       1.83
++++ libc/nscd/connections.c    26 Apr 2006 16:26:17 -0000      1.84
+@@ -1859,6 +1859,11 @@ begin_drop_privileges (void)
+ static void
+ finish_drop_privileges (void)
+ {
++#if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP
++  /* We need to preserve the capabilities to connect to the audit daemon.  */
++  cap_t new_caps = preserve_capabilities ();
++#endif
++
+   if (setgroups (server_ngroups, server_groups) == -1)
+     {
+       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
+@@ -1878,4 +1883,9 @@ finish_drop_privileges (void)
+       perror ("setuid");
+       exit (4);
+     }
++
++#if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP
++  /* Remove the temporary capabilities.  */
++  install_real_capabilities (new_caps);
++#endif
+ }
+--- libc/nscd/selinux.c        22 Feb 2006 07:30:04 -0000      1.7
++++ libc/nscd/selinux.c        26 Mar 2007 20:40:37 -0000      1.11
+@@ -27,6 +27,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <syslog.h>
++#include <sys/prctl.h>
+ #include <selinux/av_permissions.h>
+ #include <selinux/avc.h>
+ #include <selinux/flask.h>
+@@ -129,6 +130,94 @@ audit_init (void)
+   if (audit_fd < 0)
+      dbg_log (_("Failed opening connection to the audit subsystem"));
+ }
++
++
++# ifdef HAVE_LIBCAP
++static const cap_value_t new_cap_list[] =
++  { CAP_AUDIT_WRITE };
++#  define nnew_cap_list (sizeof (new_cap_list) / sizeof (new_cap_list[0]))
++static const cap_value_t tmp_cap_list[] =
++  { CAP_AUDIT_WRITE, CAP_SETUID, CAP_SETGID };
++#  define ntmp_cap_list (sizeof (tmp_cap_list) / sizeof (tmp_cap_list[0]))
++
++cap_t
++preserve_capabilities (void)
++{
++  if (getuid () != 0)
++    /* Not root, then we cannot preserve anything.  */
++    return NULL;
++
++  if (prctl (PR_SET_KEEPCAPS, 1) == -1)
++    {
++      dbg_log (_("Failed to set keep-capabilities"));
++      error (EXIT_FAILURE, errno, _("prctl(KEEPCAPS) failed"));
++      /* NOTREACHED */
++    }
++
++  cap_t tmp_caps = cap_init ();
++  cap_t new_caps;
++  if (tmp_caps != NULL)
++    new_caps = cap_init ();
++
++  if (tmp_caps == NULL || new_caps == NULL)
++    {
++      if (tmp_caps != NULL)
++      cap_free (tmp_caps);
++
++      dbg_log (_("Failed to initialize drop of capabilities"));
++      error (EXIT_FAILURE, 0, _("cap_init failed"));
++    }
++
++  /* There is no reason why these should not work.  */
++  cap_set_flag (new_caps, CAP_PERMITTED, nnew_cap_list,
++              (cap_value_t *) new_cap_list, CAP_SET);
++  cap_set_flag (new_caps, CAP_EFFECTIVE, nnew_cap_list,
++              (cap_value_t *) new_cap_list, CAP_SET);
++
++  cap_set_flag (tmp_caps, CAP_PERMITTED, ntmp_cap_list,
++              (cap_value_t *) tmp_cap_list, CAP_SET);
++  cap_set_flag (tmp_caps, CAP_EFFECTIVE, ntmp_cap_list,
++              (cap_value_t *) tmp_cap_list, CAP_SET);
++
++  int res = cap_set_proc (tmp_caps);
++
++  cap_free (tmp_caps);
++
++  if (__builtin_expect (res != 0, 0))
++    {
++      cap_free (new_caps);
++      dbg_log (_("Failed to drop capabilities\n"));
++      error (EXIT_FAILURE, 0, _("cap_set_proc failed"));
++    }
++
++  return new_caps;
++}
++
++void
++install_real_capabilities (cap_t new_caps)
++{
++  /* If we have no capabilities there is nothing to do here.  */
++  if (new_caps == NULL)
++    return;
++
++  if (cap_set_proc (new_caps))
++    {
++      cap_free (new_caps);
++      dbg_log (_("Failed to drop capabilities"));
++      error (EXIT_FAILURE, 0, _("cap_set_proc failed"));
++      /* NOTREACHED */
++    }
++
++  cap_free (new_caps);
++
++  if (prctl (PR_SET_KEEPCAPS, 0) == -1)
++    {
++      dbg_log (_("Failed to unset keep-capabilities"));
++      error (EXIT_FAILURE, errno, _("prctl(KEEPCAPS) failed"));
++      /* NOTREACHED */
++    }
++}
++# endif /* HAVE_LIBCAP */
+ #endif /* HAVE_LIBAUDIT */
+ /* Determine if we are running on an SELinux kernel. Set selinux_enabled
+--- libc/nscd/selinux.h        16 Sep 2004 23:59:44 -0000      1.2
++++ libc/nscd/selinux.h        26 Mar 2007 20:40:21 -0000      1.4
+@@ -22,6 +22,9 @@
+ #define _SELINUX_H 1
+ #include "nscd.h"
++#ifdef HAVE_LIBCAP
++# include <sys/capability.h>
++#endif
+ #ifdef HAVE_SELINUX
+ /* Global variable to tell if the kernel has SELinux support.  */
+@@ -42,6 +45,13 @@ extern int nscd_request_avc_has_perm (in
+ extern void nscd_avc_cache_stats (struct avc_cache_stats *cstats);
+ /* Display statistics on AVC usage.  */
+ extern void nscd_avc_print_stats (struct avc_cache_stats *cstats);
++
++# ifdef HAVE_LIBCAP
++/* Preserve capabilities to connect to connnect to the audit daemon.  */
++extern cap_t preserve_capabilities (void);
++/* Install final capabilities.  */
++extern void install_real_capabilities (cap_t new_caps);
++# endif
+ #else
+ # define selinux_enabled 0
+ # define nscd_avc_init() (void) 0
+--- libc/config.h.in   28 Oct 2006 06:44:04 -0000      1.80
++++ libc/config.h.in   26 Mar 2007 20:40:08 -0000      1.81
+@@ -19,6 +19,9 @@
+ /* Defined if building with SELinux support & audit libs are detected. */
+ #undef        HAVE_LIBAUDIT
++/* Defined if building with SELinux support & libcap libs are detected.  */
++#undef  HAVE_LIBCAP
++
+ /* Define if using XCOFF. Set by --with-xcoff.  */
+ #undef        HAVE_XCOFF
diff --git a/src/patches/glibc/glibc-rh184086.patch b/src/patches/glibc/glibc-rh184086.patch
new file mode 100644 (file)
index 0000000..69ec0dc
--- /dev/null
@@ -0,0 +1,37 @@
+2006-07-19  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/kaio_misc.c: Include atomic.h.
+       (kernel_callback): Ensure __return_value is updated before
+       __error_code is set.
+
+--- libc/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c.jj 2006-08-29 05:07:55.000000000 -0400
++++ libc/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c    2006-08-30 10:48:45.000000000 -0400
+@@ -27,6 +27,7 @@
+ #include <aio.h>
+ #include <assert.h>
++#include <atomic.h>
+ #include <errno.h>
+ #include <limits.h>
+ #include <pthread.h>
+@@ -381,14 +382,16 @@ static void
+ kernel_callback (kctx_t ctx, struct kiocb *kiocb, long res, long res2)
+ {
+   struct requestlist *req = (struct requestlist *)kiocb;
++  long errcode = 0;
+-  req->aiocbp->aiocb.__error_code = 0;
+-  req->aiocbp->aiocb.__return_value = res;
+   if (res < 0 && res > -1000)
+     {
+-      req->aiocbp->aiocb.__error_code = -res;
+-      req->aiocbp->aiocb.__return_value = -1;
++      errcode = -res;
++      res = -1;
+     }
++  req->aiocbp->aiocb.__return_value = res;
++  atomic_write_barrier ();
++  req->aiocbp->aiocb.__error_code = errcode;
+   __aio_notify (req);
+   assert (req->running == allocated);
+   req->running = done;
diff --git a/src/patches/glibc/glibc-rh190259.patch b/src/patches/glibc/glibc-rh190259.patch
new file mode 100644 (file)
index 0000000..22f8eb2
--- /dev/null
@@ -0,0 +1,29 @@
+2006-04-30  Ulrich Drepper  <drepper@redhat.com>
+
+       * elf/ldd.bash.in: If --verify loop fails to find a dynamic linker
+       for the file don't just try the first one listed in RTLDLIST
+       again.  We already have the status.
+
+--- libc/elf/ldd.bash.in       1 Apr 2006 20:16:17 -0000       1.36
++++ libc/elf/ldd.bash.in       30 Apr 2006 16:06:20 -0000      1.37
+@@ -154,6 +154,7 @@ for file do
+     test -x "$file" || echo 'ldd:' $"\
+ warning: you do not have execution permission for" "\`$file'" >&2
+     RTLD=
++    ret=1
+     for rtld in ${RTLDLIST}; do
+       if test -x $rtld; then
+       verify_out=`${rtld} --verify "$file"`
+@@ -163,12 +164,6 @@ warning: you do not have execution permi
+       esac
+       fi
+     done
+-    if test -z "${RTLD}"; then
+-      set ${RTLDLIST}
+-      RTLD=$1
+-      verify_out=`${RTLD} --verify "$file"`
+-      ret=$?
+-    fi
+     case $ret in
+     0)
+       # If the program exits with exit code 5, it means the process has been
diff --git a/src/patches/glibc/glibc-rh191464.patch b/src/patches/glibc/glibc-rh191464.patch
new file mode 100644 (file)
index 0000000..e0af80c
--- /dev/null
@@ -0,0 +1,250 @@
+2006-05-30  Jakub Jelinek  <jakub@redhat.com>
+
+       * nscd/nscd.h (prune_cache): Add fd argument to prototype.
+       * nscd/nscd.c (parse_opt): Read response from INVALIDATE request
+       to make sure the database has been already invalidated.
+       * nscd/cache.c (prune_cache): Add fd argument.  Write response to fd
+       after the cache has been invalidated.  Use pthread_mutex_lock rather
+       than pthread_mutex_trylock if fd != -1.
+       * nscd/connections.c (invalidate_cache): Add fd argument, write
+       response to fd if not calling prune_cache, pass fd to prune_cache.
+       (handle_request): Adjust invalidate_cache caller.
+       (nscd_run): Pass -1 as fd to prune_cache.
+
+2006-05-29  Ulrich Drepper  <drepper@redhat.com>
+
+       * nscd/nscd.h (struct database_dyn): Add prunelock field.
+       * nscd/cache.c (prune_cache): Take prunelock before starting the
+       work.  Just return in case it is already taken.
+       * nscd/connections.c (dbs): Initialize .prunelock.
+
+--- libc/nscd/cache.c  7 Dec 2005 05:47:27 -0000       1.24
++++ libc/nscd/cache.c  30 May 2006 17:30:26 -0000      1.26
+@@ -190,13 +190,34 @@ cache_add (int type, const void *key, si
+    free the data structures since some hash table entries share the same
+    data.  */
+ void
+-prune_cache (struct database_dyn *table, time_t now)
++prune_cache (struct database_dyn *table, time_t now, int fd)
+ {
+   size_t cnt = table->head->module;
+   /* If this table is not actually used don't do anything.  */
+   if (cnt == 0)
+-    return;
++    {
++      if (fd != -1)
++      {
++        /* Reply to the INVALIDATE initiator.  */
++        int32_t resp = 0;
++        writeall (fd, &resp, sizeof (resp));
++      }
++      return;
++    }
++
++  /* This function can be called from the cleanup thread but also in
++     response to an invalidate command.  Make sure only one thread is
++     running.  When not serving INVALIDATE request, no need for the
++     second to wait around.  */
++  if (fd == -1)
++    {
++      if (pthread_mutex_trylock (&table->prunelock) != 0)
++      /* The work is already being done.  */
++      return;
++    }
++  else
++    pthread_mutex_lock (&table->prunelock);
+   /* If we check for the modification of the underlying file we invalidate
+      the entries also in this case.  */
+@@ -367,6 +388,14 @@ prune_cache (struct database_dyn *table,
+     }
+   while (cnt > 0);
++  if (fd != -1)
++    {
++      /* Reply to the INVALIDATE initiator that the cache has been
++       invalidated.  */
++      int32_t resp = 0;
++      writeall (fd, &resp, sizeof (resp));
++    }
++
+   if (first <= last)
+     {
+       struct hashentry *head = NULL;
+@@ -455,4 +484,6 @@ prune_cache (struct database_dyn *table,
+   /* Run garbage collection if any entry has been removed or replaced.  */
+   if (any)
+     gc (table);
++
++  pthread_mutex_unlock (&table->prunelock);
+ }
+--- libc/nscd/connections.c    5 May 2006 06:11:54 -0000       1.55.2.24
++++ libc/nscd/connections.c    31 May 2006 15:10:34 -0000      1.55.2.25
+@@ -100,6 +100,7 @@ struct database_dyn dbs[lastdb] =
+ {
+   [pwddb] = {
+     .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
++    .prunelock = PTHREAD_MUTEX_INITIALIZER,
+     .enabled = 0,
+     .check_file = 1,
+     .persistent = 0,
+@@ -117,6 +118,7 @@ struct database_dyn dbs[lastdb] =
+   },
+   [grpdb] = {
+     .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
++    .prunelock = PTHREAD_MUTEX_INITIALIZER,
+     .enabled = 0,
+     .check_file = 1,
+     .persistent = 0,
+@@ -134,6 +136,7 @@ struct database_dyn dbs[lastdb] =
+   },
+   [hstdb] = {
+     .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
++    .prunelock = PTHREAD_MUTEX_INITIALIZER,
+     .enabled = 0,
+     .check_file = 1,
+     .persistent = 0,
+@@ -813,9 +816,10 @@ close_sockets (void)
+ static void
+-invalidate_cache (char *key)
++invalidate_cache (char *key, int fd)
+ {
+   dbtype number;
++  int32_t resp;
+   if (strcmp (key, "passwd") == 0)
+     number = pwddb;
+@@ -829,10 +833,19 @@ invalidate_cache (char *key)
+       res_init ();
+     }
+   else
+-    return;
++    {
++      resp = EINVAL;
++      writeall (fd, &resp, sizeof (resp));
++      return;
++    }
+   if (dbs[number].enabled)
+-    prune_cache (&dbs[number], LONG_MAX);
++    prune_cache (&dbs[number], LONG_MAX, fd);
++  else
++    {
++      resp = 0;
++      writeall (fd, &resp, sizeof (resp));
++    }
+ }
+@@ -1089,7 +1102,7 @@ cannot handle old request version %d; cu
+       else if (uid == 0)
+       {
+         if (req->type == INVALIDATE)
+-          invalidate_cache (key);
++          invalidate_cache (key, fd);
+         else
+           termination_handler (0);
+       }
+@@ -1435,7 +1448,7 @@ handle_request: request received (Versio
+         /* The pthread_cond_timedwait() call timed out.  It is time
+                to clean up the cache.  */
+         assert (my_number < lastdb);
+-        prune_cache (&dbs[my_number], time (NULL));
++        prune_cache (&dbs[my_number], time (NULL), -1);
+         if (clock_gettime (timeout_clock, &prune_ts) == -1)
+           /* Should never happen.  */
+@@ -1908,14 +1921,14 @@ sighup_handler (int signum)
+ {
+   /* Prune the password database.  */
+   if (dbs[pwddb].enabled)
+-    prune_cache (&dbs[pwddb], LONG_MAX);
++    prune_cache (&dbs[pwddb], LONG_MAX, -1);
+     
+   /* Prune the group database.  */
+   if (dbs[grpdb].enabled)
+-    prune_cache (&dbs[grpdb], LONG_MAX);
++    prune_cache (&dbs[grpdb], LONG_MAX, -1);
+   /* Prune the host database.  */
+   if (dbs[hstdb].enabled)
+-    prune_cache (&dbs[hstdb], LONG_MAX);
++    prune_cache (&dbs[hstdb], LONG_MAX, -1);
+ }
+--- libc/nscd/nscd.c   6 Apr 2006 22:55:50 -0000       1.52
++++ libc/nscd/nscd.c   30 May 2006 17:29:36 -0000      1.53
+@@ -332,9 +332,6 @@ parse_opt (int key, char *arg, struct ar
+           exit (EXIT_FAILURE);
+         request_header req;
+-        ssize_t nbytes;
+-        struct iovec iov[2];
+-
+         if (strcmp (arg, "passwd") == 0)
+           req.key_len = sizeof "passwd";
+         else if (strcmp (arg, "group") == 0)
+@@ -347,17 +344,38 @@ parse_opt (int key, char *arg, struct ar
+         req.version = NSCD_VERSION;
+         req.type = INVALIDATE;
++        struct iovec iov[2];
+         iov[0].iov_base = &req;
+         iov[0].iov_len = sizeof (req);
+         iov[1].iov_base = arg;
+         iov[1].iov_len = req.key_len;
+-        nbytes = TEMP_FAILURE_RETRY (writev (sock, iov, 2));
++        ssize_t nbytes = TEMP_FAILURE_RETRY (writev (sock, iov, 2));
++
++        if (nbytes != iov[0].iov_len + iov[1].iov_len)
++          {
++            int err = errno;
++            close (sock);
++            error (EXIT_FAILURE, err, _("write incomplete"));
++          }
++
++        /* Wait for ack.  Older nscd just closed the socket when
++           prune_cache finished, silently ignore that.  */
++        int32_t resp = 0;
++        nbytes = TEMP_FAILURE_RETRY (read (sock, &resp, sizeof (resp)));
++        if (nbytes != 0 && nbytes != sizeof (resp))
++          {
++            int err = errno;
++            close (sock);
++            error (EXIT_FAILURE, err, _("cannot read invalidate ACK"));
++          }
+         close (sock);
+-        exit (nbytes != iov[0].iov_len + iov[1].iov_len
+-              ? EXIT_FAILURE : EXIT_SUCCESS);
++        if (resp != 0)
++          error (EXIT_FAILURE, resp, _("invalidation failed"));
++
++        exit (0);
+       }
+     case 't':
+--- libc/nscd/nscd.h   30 Apr 2006 16:37:49 -0000      1.26
++++ libc/nscd/nscd.h   30 May 2006 17:28:53 -0000      1.28
+@@ -58,6 +58,7 @@ typedef enum
+ struct database_dyn
+ {
+   pthread_rwlock_t lock;
++  pthread_mutex_t prunelock;
+   int enabled;
+   int check_file;
+@@ -184,7 +185,7 @@ extern struct datahead *cache_search (re
+ extern int cache_add (int type, const void *key, size_t len,
+                     struct datahead *packet, bool first,
+                     struct database_dyn *table, uid_t owner);
+-extern void prune_cache (struct database_dyn *table, time_t now);
++extern void prune_cache (struct database_dyn *table, time_t now, int fd);
+ /* pwdcache.c */
+ extern void addpwbyname (struct database_dyn *db, int fd, request_header *req,
diff --git a/src/patches/glibc/glibc-rh192072.patch b/src/patches/glibc/glibc-rh192072.patch
new file mode 100644 (file)
index 0000000..7d9f8c4
--- /dev/null
@@ -0,0 +1,508 @@
+2006-07-31  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nss_compat/compat-grp.c: Avoid unnecessary setgrent calls into
+       the backend NSS module.  If backend setgrent call failed, don't have
+       internal_setgrent fail.  Just remember this until it is needed.
+       * nis/nss_compat/compat-pwd.c: Likewise.
+       * nis/nss_compat/compat-spwd.c: Likewise.
+
+--- libc/nis/nss_compat/compat-grp.c   18 May 2006 14:51:05 -0000      1.31
++++ libc/nis/nss_compat/compat-grp.c   31 Jul 2006 23:33:04 -0000      1.32
+@@ -59,12 +59,13 @@ struct blacklist_t
+ struct ent_t
+ {
+   bool_t files;
++  enum nss_status setent_status;
+   FILE *stream;
+   struct blacklist_t blacklist;
+ };
+ typedef struct ent_t ent_t;
+-static ent_t ext_ent = {TRUE, NULL, {NULL, 0, 0}};
++static ent_t ext_ent = { TRUE, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }};
+ /* Protect global state against multiple changers.  */
+ __libc_lock_define_initialized (static, lock)
+@@ -89,7 +90,7 @@ init_nss_interface (void)
+ }
+ static enum nss_status
+-internal_setgrent (ent_t *ent, int stayopen)
++internal_setgrent (ent_t *ent, int stayopen, int needent)
+ {
+   enum nss_status status = NSS_STATUS_SUCCESS;
+@@ -137,12 +138,8 @@ internal_setgrent (ent_t *ent, int stayo
+   else
+     rewind (ent->stream);
+-  if (status == NSS_STATUS_SUCCESS && nss_setgrent)
+-    {
+-      status = nss_setgrent (stayopen);
+-      if (status == NSS_STATUS_UNAVAIL)
+-        status = NSS_STATUS_SUCCESS;
+-    }
++  if (needent && status == NSS_STATUS_SUCCESS && nss_setgrent)
++    ent->setent_status = nss_setgrent (stayopen);
+   return status;
+ }
+@@ -158,7 +155,7 @@ _nss_compat_setgrent (int stayopen)
+   if (ni == NULL)
+     init_nss_interface ();
+-  result = internal_setgrent (&ext_ent, stayopen);
++  result = internal_setgrent (&ext_ent, stayopen, 1);
+   __libc_lock_unlock (lock);
+@@ -212,6 +209,10 @@ getgrent_next_nss (struct group *result,
+   if (!nss_getgrent_r)
+     return NSS_STATUS_UNAVAIL;
++  /* If the setgrent call failed, say so.  */
++  if (ent->setent_status != NSS_STATUS_SUCCESS)
++    return ent->setent_status;
++
+   do
+     {
+       enum nss_status status;
+@@ -363,7 +364,7 @@ _nss_compat_getgrent_r (struct group *gr
+     init_nss_interface ();
+   if (ext_ent.stream == NULL)
+-    result = internal_setgrent (&ext_ent, 1);
++    result = internal_setgrent (&ext_ent, 1, 1);
+   if (result == NSS_STATUS_SUCCESS)
+     {
+@@ -485,7 +486,7 @@ enum nss_status
+ _nss_compat_getgrnam_r (const char *name, struct group *grp,
+                       char *buffer, size_t buflen, int *errnop)
+ {
+-  ent_t ent = {TRUE, NULL, {NULL, 0, 0}};
++  ent_t ent = { TRUE, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }};
+   enum nss_status result;
+   if (name[0] == '-' || name[0] == '+')
+@@ -498,7 +499,7 @@ _nss_compat_getgrnam_r (const char *name
+   __libc_lock_unlock (lock);
+-  result = internal_setgrent (&ent, 0);
++  result = internal_setgrent (&ent, 0, 0);
+   if (result == NSS_STATUS_SUCCESS)
+     result = internal_getgrnam_r (name, grp, &ent, buffer, buflen, errnop);
+@@ -613,7 +614,7 @@ enum nss_status
+ _nss_compat_getgrgid_r (gid_t gid, struct group *grp,
+                       char *buffer, size_t buflen, int *errnop)
+ {
+-  ent_t ent = {TRUE, NULL, {NULL, 0, 0}};
++  ent_t ent = { TRUE, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }};
+   enum nss_status result;
+   __libc_lock_lock (lock);
+@@ -623,7 +624,7 @@ _nss_compat_getgrgid_r (gid_t gid, struc
+   __libc_lock_unlock (lock);
+-  result = internal_setgrent (&ent, 0);
++  result = internal_setgrent (&ent, 0, 0);
+   if (result == NSS_STATUS_SUCCESS)
+     result = internal_getgrgid_r (gid, grp, &ent, buffer, buflen, errnop);
+--- libc/nis/nss_compat/compat-pwd.c   18 May 2006 14:51:05 -0000      1.36
++++ libc/nis/nss_compat/compat-pwd.c   31 Jul 2006 23:33:04 -0000      1.37
+@@ -62,9 +62,10 @@ struct blacklist_t
+ struct ent_t
+ {
+-  bool_t netgroup;
+-  bool_t first;
+-  bool_t files;
++  bool netgroup;
++  bool first;
++  bool files;
++  enum nss_status setent_status;
+   FILE *stream;
+   struct blacklist_t blacklist;
+   struct passwd pwd;
+@@ -72,8 +73,9 @@ struct ent_t
+ };
+ typedef struct ent_t ent_t;
+-static ent_t ext_ent = {0, 0, TRUE, NULL, {NULL, 0, 0},
+-                        {NULL, NULL, 0, 0, NULL, NULL, NULL}};
++static ent_t ext_ent = { false, false, true, NSS_STATUS_SUCCESS, NULL,
++                       { NULL, 0, 0 },
++                       { NULL, NULL, 0, 0, NULL, NULL, NULL }};
+ /* Protect global state against multiple changers.  */
+ __libc_lock_define_initialized (static, lock)
+@@ -202,12 +204,13 @@ copy_pwd_changes (struct passwd *dest, s
+ }
+ static enum nss_status
+-internal_setpwent (ent_t *ent, int stayopen)
++internal_setpwent (ent_t *ent, int stayopen, int needent)
+ {
+   enum nss_status status = NSS_STATUS_SUCCESS;
+-  ent->first = ent->netgroup = FALSE;
+-  ent->files = TRUE;
++  ent->first = ent->netgroup = false;
++  ent->files = true;
++  ent->setent_status = NSS_STATUS_SUCCESS;
+   /* If something was left over free it.  */
+   if (ent->netgroup)
+@@ -257,12 +260,8 @@ internal_setpwent (ent_t *ent, int stayo
+   give_pwd_free (&ent->pwd);
+-  if (status == NSS_STATUS_SUCCESS && nss_setpwent)
+-    {
+-      status = nss_setpwent (stayopen);
+-      if (status == NSS_STATUS_UNAVAIL)
+-        status = NSS_STATUS_SUCCESS;
+-    }
++  if (needent && status == NSS_STATUS_SUCCESS && nss_setpwent)
++    ent->setent_status = nss_setpwent (stayopen);
+   return status;
+ }
+@@ -278,7 +277,7 @@ _nss_compat_setpwent (int stayopen)
+   if (ni == NULL)
+     init_nss_interface ();
+-  result = internal_setpwent (&ext_ent, stayopen);
++  result = internal_setpwent (&ext_ent, stayopen, 1);
+   __libc_lock_unlock (lock);
+@@ -301,7 +300,7 @@ internal_endpwent (ent_t *ent)
+   if (ent->netgroup)
+     __internal_endnetgrent (&ent->netgrdata);
+-  ent->first = ent->netgroup = FALSE;
++  ent->first = ent->netgroup = false;
+   if (ent->blacklist.data != NULL)
+     {
+@@ -348,17 +347,17 @@ getpwent_next_nss_netgr (const char *nam
+   if (yp_get_default_domain (&curdomain) != YPERR_SUCCESS)
+     {
+-      ent->netgroup = FALSE;
+-      ent->first = FALSE;
++      ent->netgroup = false;
++      ent->first = false;
+       give_pwd_free (&ent->pwd);
+       return NSS_STATUS_UNAVAIL;
+     }
+-  if (ent->first == TRUE)
++  if (ent->first == true)
+     {
+       memset (&ent->netgrdata, 0, sizeof (struct __netgrent));
+       __internal_setnetgrent (group, &ent->netgrdata);
+-      ent->first = FALSE;
++      ent->first = false;
+     }
+   while (1)
+@@ -427,6 +426,10 @@ getpwent_next_nss (struct passwd *result
+   if (!nss_getpwent_r)
+     return NSS_STATUS_UNAVAIL;
++  /* If the setpwent call failed, say so.  */
++  if (ent->setent_status != NSS_STATUS_SUCCESS)
++    return ent->setent_status;
++
+   p2len = pwd_need_buflen (&ent->pwd);
+   if (p2len > buflen)
+     {
+@@ -437,7 +440,7 @@ getpwent_next_nss (struct passwd *result
+   buflen -= p2len;
+   if (ent->first)
+-    ent->first = FALSE;
++    ent->first = false;
+   do
+     {
+@@ -570,8 +573,8 @@ getpwent_next_file (struct passwd *resul
+       {
+         enum nss_status status;
+-        ent->netgroup = TRUE;
+-        ent->first = TRUE;
++        ent->netgroup = true;
++        ent->first = true;
+         copy_pwd_changes (&ent->pwd, result, NULL, 0);
+         status = getpwent_next_nss_netgr (NULL, result, ent,
+@@ -626,8 +629,8 @@ getpwent_next_file (struct passwd *resul
+       /* +:... */
+       if (result->pw_name[0] == '+' && result->pw_name[1] == '\0')
+       {
+-        ent->files = FALSE;
+-        ent->first = TRUE;
++        ent->files = false;
++        ent->first = true;
+         copy_pwd_changes (&ent->pwd, result, NULL, 0);
+         return getpwent_next_nss (result, ent, buffer, buflen, errnop);
+@@ -675,7 +678,7 @@ _nss_compat_getpwent_r (struct passwd *p
+     init_nss_interface ();
+   if (ext_ent.stream == NULL)
+-    result = internal_setpwent (&ext_ent, 1);
++    result = internal_setpwent (&ext_ent, 1, 1);
+   if (result == NSS_STATUS_SUCCESS)
+     result = internal_getpwent_r (pwd, &ext_ent, buffer, buflen, errnop);
+@@ -827,8 +830,8 @@ _nss_compat_getpwnam_r (const char *name
+                       char *buffer, size_t buflen, int *errnop)
+ {
+   enum nss_status result;
+-  ent_t ent = {0, 0, TRUE, NULL, {NULL, 0, 0},
+-               {NULL, NULL, 0, 0, NULL, NULL, NULL}};
++  ent_t ent = { false, false, true, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 },
++              { NULL, NULL, 0, 0, NULL, NULL, NULL }};
+   if (name[0] == '-' || name[0] == '+')
+     return NSS_STATUS_NOTFOUND;
+@@ -840,7 +843,7 @@ _nss_compat_getpwnam_r (const char *name
+   __libc_lock_unlock (lock);
+-  result = internal_setpwent (&ent, 0);
++  result = internal_setpwent (&ent, 0, 0);
+   if (result == NSS_STATUS_SUCCESS)
+     result = internal_getpwnam_r (name, pwd, &ent, buffer, buflen, errnop);
+@@ -1069,8 +1072,8 @@ _nss_compat_getpwuid_r (uid_t uid, struc
+                       char *buffer, size_t buflen, int *errnop)
+ {
+   enum nss_status result;
+-  ent_t ent = {0, 0, TRUE, NULL, {NULL, 0, 0},
+-               {NULL, NULL, 0, 0, NULL, NULL, NULL}};
++  ent_t ent = { false, false, true, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 },
++              { NULL, NULL, 0, 0, NULL, NULL, NULL }};
+   __libc_lock_lock (lock);
+@@ -1079,7 +1082,7 @@ _nss_compat_getpwuid_r (uid_t uid, struc
+   __libc_lock_unlock (lock);
+-  result = internal_setpwent (&ent, 0);
++  result = internal_setpwent (&ent, 0, 0);
+   if (result == NSS_STATUS_SUCCESS)
+     result = internal_getpwuid_r (uid, pwd, &ent, buffer, buflen, errnop);
+@@ -1136,7 +1139,7 @@ blacklist_store_name (const char *name, 
+   return;
+ }
+-/* returns TRUE if ent->blacklist contains name, else FALSE */
++/* Returns TRUE if ent->blacklist contains name, else FALSE.  */
+ static bool_t
+ in_blacklist (const char *name, int namelen, ent_t *ent)
+ {
+--- libc/nis/nss_compat/compat-spwd.c  18 May 2006 14:51:05 -0000      1.29
++++ libc/nis/nss_compat/compat-spwd.c  31 Jul 2006 23:33:04 -0000      1.30
+@@ -59,9 +59,10 @@ struct blacklist_t
+ struct ent_t
+ {
+-  bool_t netgroup;
+-  bool_t files;
+-  bool_t first;
++  bool netgroup;
++  bool files;
++  bool first;
++  enum nss_status setent_status;
+   FILE *stream;
+   struct blacklist_t blacklist;
+   struct spwd pwd;
+@@ -69,8 +70,9 @@ struct ent_t
+ };
+ typedef struct ent_t ent_t;
+-static ent_t ext_ent = {0, TRUE, 0, NULL, {NULL, 0, 0},
+-                      {NULL, NULL, 0, 0, 0, 0, 0, 0, 0}};
++static ent_t ext_ent = { false, true, false, NSS_STATUS_SUCCESS, NULL,
++                       { NULL, 0, 0},
++                       { NULL, NULL, 0, 0, 0, 0, 0, 0, 0}};
+ /* Protect global state against multiple changers.  */
+ __libc_lock_define_initialized (static, lock)
+@@ -161,7 +163,7 @@ internal_setspent (ent_t *ent, int stayo
+   enum nss_status status = NSS_STATUS_SUCCESS;
+   ent->first = ent->netgroup = 0;
+-  ent->files = TRUE;
++  ent->files = true;
+   /* If something was left over free it.  */
+   if (ent->netgroup)
+@@ -212,11 +214,7 @@ internal_setspent (ent_t *ent, int stayo
+   give_spwd_free (&ent->pwd);
+   if (status == NSS_STATUS_SUCCESS && nss_setspent)
+-    {
+-      status = nss_setspent (stayopen);
+-      if (status == NSS_STATUS_UNAVAIL)
+-        status = NSS_STATUS_SUCCESS;
+-    }
++    ent->setent_status = nss_setspent (stayopen);
+   return status;
+ }
+@@ -255,8 +253,8 @@ internal_endspent (ent_t *ent)
+   if (ent->netgroup)
+     __internal_endnetgrent (&ent->netgrdata);
+-  ent->first = ent->netgroup = FALSE;
+-  ent->files = TRUE;
++  ent->first = ent->netgroup = false;
++  ent->files = true;
+   if (ent->blacklist.data != NULL)
+     {
+@@ -298,19 +296,23 @@ getspent_next_nss_netgr (const char *nam
+   if (!nss_getspnam_r)
+     return NSS_STATUS_UNAVAIL;
++  /* If the setpwent call failed, say so.  */
++  if (ent->setent_status != NSS_STATUS_SUCCESS)
++    return ent->setent_status;
++
+   if (yp_get_default_domain (&curdomain) != YPERR_SUCCESS)
+     {
+-      ent->netgroup = FALSE;
+-      ent->first = FALSE;
++      ent->netgroup = false;
++      ent->first = false;
+       give_spwd_free (&ent->pwd);
+       return NSS_STATUS_UNAVAIL;
+     }
+-  if (ent->first == TRUE)
++  if (ent->first == true)
+     {
+       memset (&ent->netgrdata, 0, sizeof (struct __netgrent));
+       __internal_setnetgrent (group, &ent->netgrdata);
+-      ent->first = FALSE;
++      ent->first = false;
+     }
+   while (1)
+@@ -325,7 +327,7 @@ getspent_next_nss_netgr (const char *nam
+       if (status != 1)
+       {
+         __internal_endnetgrent (&ent->netgrdata);
+-        ent->netgroup = FALSE;
++        ent->netgroup = false;
+         give_spwd_free (&ent->pwd);
+         return NSS_STATUS_RETURN;
+       }
+@@ -400,6 +402,7 @@ getspent_next_nss (struct spwd *result, 
+   return NSS_STATUS_SUCCESS;
+ }
++
+ /* This function handle the +user entrys in /etc/shadow */
+ static enum nss_status
+ getspnam_plususer (const char *name, struct spwd *result, ent_t *ent,
+@@ -440,6 +443,7 @@ getspnam_plususer (const char *name, str
+   return NSS_STATUS_SUCCESS;
+ }
++
+ static enum nss_status
+ getspent_next_file (struct spwd *result, ent_t *ent,
+                   char *buffer, size_t buflen, int *errnop)
+@@ -520,8 +524,8 @@ getspent_next_file (struct spwd *result,
+       {
+         int status;
+-        ent->netgroup = TRUE;
+-        ent->first = TRUE;
++        ent->netgroup = true;
++        ent->first = true;
+         copy_spwd_changes (&ent->pwd, result, NULL, 0);
+         status = getspent_next_nss_netgr (NULL, result, ent,
+@@ -577,8 +581,8 @@ getspent_next_file (struct spwd *result,
+       /* +:... */
+       if (result->sp_namp[0] == '+' && result->sp_namp[1] == '\0')
+       {
+-        ent->files = FALSE;
+-        ent->first = TRUE;
++        ent->files = false;
++        ent->first = true;
+         copy_spwd_changes (&ent->pwd, result, NULL, 0);
+         return getspent_next_nss (result, ent, buffer, buflen, errnop);
+@@ -613,6 +617,7 @@ internal_getspent_r (struct spwd *pw, en
+     return getspent_next_nss (pw, ent, buffer, buflen, errnop);
+ }
++
+ enum nss_status
+ _nss_compat_getspent_r (struct spwd *pwd, char *buffer, size_t buflen,
+                       int *errnop)
+@@ -636,6 +641,7 @@ _nss_compat_getspent_r (struct spwd *pwd
+   return result;
+ }
++
+ /* Searches in /etc/passwd and the NIS/NIS+ map for a special user */
+ static enum nss_status
+ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent,
+@@ -778,13 +784,14 @@ internal_getspnam_r (const char *name, s
+   return NSS_STATUS_SUCCESS;
+ }
++
+ enum nss_status
+ _nss_compat_getspnam_r (const char *name, struct spwd *pwd,
+                       char *buffer, size_t buflen, int *errnop)
+ {
+   enum nss_status result;
+-  ent_t ent = {0, TRUE, 0, NULL, {NULL, 0, 0},
+-             {NULL, NULL, 0, 0, 0, 0, 0, 0, 0}};
++  ent_t ent = { false, true, false, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0},
++              { NULL, NULL, 0, 0, 0, 0, 0, 0, 0}};
+   if (name[0] == '-' || name[0] == '+')
+     return NSS_STATUS_NOTFOUND;
+@@ -806,6 +813,7 @@ _nss_compat_getspnam_r (const char *name
+   return result;
+ }
++
+ /* Support routines for remembering -@netgroup and -user entries.
+    The names are stored in a single string with `|' as separator. */
+ static void
+@@ -852,6 +860,7 @@ blacklist_store_name (const char *name, 
+   return;
+ }
++
+ /* Returns TRUE if ent->blacklist contains name, else FALSE.  */
+ static bool_t
+ in_blacklist (const char *name, int namelen, ent_t *ent)
+@@ -860,7 +869,7 @@ in_blacklist (const char *name, int name
+   char *cp;
+   if (ent->blacklist.data == NULL)
+-    return FALSE;
++    return false;
+   buf[0] = '|';
+   cp = stpcpy (&buf[1], name);
diff --git a/src/patches/glibc/glibc-rh193631.patch b/src/patches/glibc/glibc-rh193631.patch
new file mode 100644 (file)
index 0000000..7a27a7a
--- /dev/null
@@ -0,0 +1,85 @@
+2006-06-04  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/posix/spawni.c (__spawni): Use local_seteuid and
+       local_setegid instead of seteuid and setegid.
+       * sysdeps/generic/local-setxid.h: New file.
+       * sysdeps/unix/sysv/linux/local-setxid.h: New file.
+
+       * sysdeps/posix/spawni.c (__spawni): Use non-cancelable interfaces.
+
+--- libc/sysdeps/generic/local-setxid.h        1 Jan 1970 00:00:00 -0000
++++ libc/sysdeps/generic/local-setxid.h        4 Jun 2006 22:15:39 -0000       1.1
+@@ -0,0 +1,4 @@
++/* No special support.  Fall back to the regular functions.  */
++
++#define local_seteuid(id) seteuid (id)
++#define local_setegid(id) setegid (id)
+--- libc/sysdeps/posix/spawni.c        13 Sep 2005 18:41:48 -0000      1.7
++++ libc/sysdeps/posix/spawni.c        4 Jun 2006 22:16:05 -0000       1.9
+@@ -26,6 +26,7 @@
+ #include <unistd.h>
+ #include "spawn_int.h"
+ #include <not-cancel.h>
++#include <local-setxid.h>
+ /* The Unix standard contains a long explanation of the way to signal
+@@ -155,7 +156,8 @@ __spawni (pid_t *pid, const char *file,
+   /* Set the effective user and group IDs.  */
+   if ((flags & POSIX_SPAWN_RESETIDS) != 0
+-      && (seteuid (__getuid ()) != 0 || setegid (__getgid ()) != 0))
++      && (local_seteuid (__getuid ()) != 0
++        || local_setegid (__getgid ()) != 0))
+     _exit (SPAWN_ERROR);
+   /* Execute the file actions.  */
+@@ -177,9 +179,10 @@ __spawni (pid_t *pid, const char *file,
+           case spawn_do_open:
+             {
+-              int new_fd = __open64 (action->action.open_action.path,
+-                                     action->action.open_action.oflag,
+-                                     action->action.open_action.mode);
++              int new_fd = open_not_cancel (action->action.open_action.path,
++                                            action->action.open_action.oflag
++                                            | O_LARGEFILE,
++                                            action->action.open_action.mode);
+               if (new_fd == -1)
+                 /* The `open' call failed.  */
+@@ -193,7 +196,7 @@ __spawni (pid_t *pid, const char *file,
+                     /* The `dup2' call failed.  */
+                     _exit (SPAWN_ERROR);
+-                  if (__close (new_fd) != 0)
++                  if (close_not_cancel (new_fd) != 0)
+                     /* The `close' call failed.  */
+                     _exit (SPAWN_ERROR);
+                 }
+--- libc/sysdeps/unix/sysv/linux/local-setxid.h        1 Jan 1970 00:00:00 -0000
++++ libc/sysdeps/unix/sysv/linux/local-setxid.h        4 Jun 2006 22:15:39 -0000       1.1
+@@ -0,0 +1,23 @@
++/* SETxID functions which only have to change the local thread and
++   none of the possible other threads.  */
++#include <kernel-features.h>
++#include <sysdep.h>
++
++/* If we can use the syscall directly, use it.  */
++#if __ASSUME_32BITUIDS > 0 && defined __NR_setresuid32
++# define local_seteuid(id) INLINE_SYSCALL (setresuid32, 3, -1, id, -1)
++#elif __ASSUME_SETRESUID_SYSCALL > 0
++# define local_seteuid(id) INLINE_SYSCALL (setresuid, 3, -1, id, -1)
++#else
++# define local_seteuid(id) seteuid (id)
++#endif
++
++
++/* If we can use the syscall directly, use it.  */
++#if __ASSUME_32BITUIDS > 0 && defined __NR_setresgid32
++# define local_setegid(id) INLINE_SYSCALL (setresgid32, 3, -1, id, -1)
++#elif __ASSUME_SETRESGID_SYSCALL > 0
++# define local_setegid(id) INLINE_SYSCALL (setresgid, 3, -1, id, -1)
++#else
++# define local_setegid(id) setegid (id)
++#endif
diff --git a/src/patches/glibc/glibc-rh193873.patch b/src/patches/glibc/glibc-rh193873.patch
new file mode 100644 (file)
index 0000000..7b7ea89
--- /dev/null
@@ -0,0 +1,158 @@
+2006-06-02  Jakub Jelinek  <jakub@redhat.com>
+
+       * posix/regex_internal.c (re_string_skip_chars): If no character has
+       been converted at all, set *last_wc to WEOF.  If mbrtowc failed, set wc
+       to the byte which couldn't be converted.
+       (re_string_reconstruct): Don't clear valid_raw_len before calling
+       re_string_skip_chars.  If wc is WEOF after re_string_skip_chars, set
+       tip_context using re_string_context_at.
+       * posix/Makefile: Add rules to build and run bug-regex25 test.
+       * posix/bug-regex25.c: New test.
+
+--- libc/posix/Makefile        30 Apr 2006 20:16:28 -0000      1.190
++++ libc/posix/Makefile        4 Jun 2006 04:59:05 -0000       1.191
+@@ -81,7 +81,7 @@ tests                := tstgetopt testfnm runtests run
+                  bug-regex13 bug-regex14 bug-regex15 bug-regex16 \
+                  bug-regex17 bug-regex18 bug-regex19 bug-regex20 \
+                  bug-regex21 bug-regex22 bug-regex23 bug-regex24 \
+-                 tst-nice tst-nanosleep tst-regex2 \
++                 bug-regex25 tst-nice tst-nanosleep tst-regex2 \
+                  transbug tst-rxspencer tst-pcre tst-boost \
+                  bug-ga1 tst-vfork1 tst-vfork2 tst-waitid \
+                  tst-getaddrinfo2 bug-glob1 bug-glob2 tst-sysconf \
+@@ -188,6 +188,7 @@ bug-regex19-ENV = LOCPATH=$(common-objpf
+ bug-regex20-ENV = LOCPATH=$(common-objpfx)localedata
+ bug-regex22-ENV = LOCPATH=$(common-objpfx)localedata
+ bug-regex23-ENV = LOCPATH=$(common-objpfx)localedata
++bug-regex25-ENV = LOCPATH=$(common-objpfx)localedata
+ tst-rxspencer-ARGS = --utf8 rxspencer/tests
+ tst-rxspencer-ENV = LOCPATH=$(common-objpfx)localedata
+ tst-pcre-ARGS = PCRE.tests
+--- libc/posix/bug-regex25.c   1 Jan 1970 00:00:00 -0000
++++ libc/posix/bug-regex25.c   4 Jun 2006 04:58:35 -0000       1.1
+@@ -0,0 +1,57 @@
++/* Test re_search in multibyte locale other than UTF-8.
++   Copyright (C) 2006 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <locale.h>
++#include <regex.h>
++#include <stdio.h>
++#include <string.h>
++
++const char *str1 = "\xa3\xd8\xa3\xc9\xa3\xc9";
++const char *str2 = "\xa3\xd8\xa3\xc9";
++
++int
++main (void)
++{
++  setlocale (LC_ALL, "ja_JP.eucJP");
++
++  re_set_syntax (RE_SYNTAX_SED);
++
++  struct re_pattern_buffer re;
++  memset (&re, 0, sizeof (re));
++
++  struct re_registers regs;
++  memset (&regs, 0, sizeof (regs));
++
++  re_compile_pattern ("$", 1, &re);
++
++  int ret = 0, r = re_search (&re, str1, 4, 0, 4, &regs);
++  if (r != 4)
++    {
++      printf ("First re_search returned %d\n", r);
++      ret = 1;
++    }
++  r = re_search (&re, str2, 4, 0, 4, &regs);
++  if (r != 4)
++    {
++      printf ("Second re_search returned %d\n", r);
++      ret = 1;
++    }
++  return ret;
++}
+--- libc/posix/regex_internal.c        15 Jan 2006 17:49:28 -0000      1.65
++++ libc/posix/regex_internal.c        4 Jun 2006 04:57:19 -0000       1.66
+@@ -497,7 +497,7 @@ re_string_skip_chars (pstr, new_raw_idx,
+ {
+   mbstate_t prev_st;
+   int rawbuf_idx, mbclen;
+-  wchar_t wc = 0;
++  wchar_t wc = WEOF;
+   /* Skip the characters which are not necessary to check.  */
+   for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len;
+@@ -510,7 +510,11 @@ re_string_skip_chars (pstr, new_raw_idx,
+                       remain_len, &pstr->cur_state);
+       if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0))
+       {
+-        /* We treat these cases as a singlebyte character.  */
++        /* We treat these cases as a single byte character.  */
++        if (mbclen == 0 || remain_len == 0)
++          wc = L'\0';
++        else
++          wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx);
+         mbclen = 1;
+         pstr->cur_state = prev_st;
+       }
+@@ -634,7 +638,6 @@ re_string_reconstruct (pstr, idx, eflags
+           }
+ #endif
+         pstr->valid_len = 0;
+-        pstr->valid_raw_len = 0;
+ #ifdef RE_ENABLE_I18N
+         if (pstr->mb_cur_max > 1)
+           {
+@@ -683,6 +686,16 @@ re_string_reconstruct (pstr, idx, eflags
+             if (wc == WEOF)
+               pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx;
++            if (wc == WEOF)
++              pstr->tip_context
++                = re_string_context_at (pstr, pstr->valid_raw_len - 1, eflags);
++            else
++              pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0)
++                                    && IS_WIDE_WORD_CHAR (wc))
++                                   ? CONTEXT_WORD
++                                   : ((IS_WIDE_NEWLINE (wc)
++                                       && pstr->newline_anchor)
++                                      ? CONTEXT_NEWLINE : 0));
+             if (BE (pstr->valid_len, 0))
+               {
+                 for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx)
+@@ -691,17 +704,12 @@ re_string_reconstruct (pstr, idx, eflags
+                   memset (pstr->mbs, 255, pstr->valid_len);
+               }
+             pstr->valid_raw_len = pstr->valid_len;
+-            pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0)
+-                                  && IS_WIDE_WORD_CHAR (wc))
+-                                 ? CONTEXT_WORD
+-                                 : ((IS_WIDE_NEWLINE (wc)
+-                                     && pstr->newline_anchor)
+-                                    ? CONTEXT_NEWLINE : 0));
+           }
+         else
+ #endif /* RE_ENABLE_I18N */
+           {
+             int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1];
++            pstr->valid_raw_len = 0;
+             if (pstr->trans)
+               c = pstr->trans[c];
+             pstr->tip_context = (bitset_contain (pstr->word_char, c)
diff --git a/src/patches/glibc/glibc-rh194321.patch b/src/patches/glibc/glibc-rh194321.patch
new file mode 100644 (file)
index 0000000..b04f247
--- /dev/null
@@ -0,0 +1,81 @@
+2006-06-22  Ulrich Drepper  <drepper@redhat.com>
+
+       * intl/dcigettext.c (DCIGETTEXT): If _nl_find_msg returns -1 don't
+       look further, return original strings.
+       (_nl_find_msg): Do not return found translation if the conversion
+       failed.  Either signal the string is unusable or that something went
+       wrong and the original should be used.
+
+--- libc/intl/dcigettext.c     15 May 2006 18:31:52 -0000      1.52
++++ libc/intl/dcigettext.c     22 Jun 2006 23:58:37 -0000      1.53
+@@ -581,6 +581,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, 
+       if (strcmp (single_locale, "C") == 0
+         || strcmp (single_locale, "POSIX") == 0)
+       {
++      no_translation:
+         FREE_BLOCKS (block_list);
+         __libc_rwlock_unlock (_nl_state_lock);
+         __set_errno (saved_errno);
+@@ -616,6 +617,12 @@ DCIGETTEXT (domainname, msgid1, msgid2, 
+               }
+           }
++        /* Returning -1 means that some resource problem exists
++           (likely memory) and that the strings could not be
++           converted.  Return the original strings.  */
++        if (__builtin_expect (retval == (char *) -1, 0))
++          goto no_translation;
++
+         if (retval != NULL)
+           {
+             /* Found the translation of MSGID1 in domain DOMAIN:
+@@ -829,8 +836,9 @@ _nl_find_msg (domain_file, domainbinding
+       domain->conv_tab = (char **) -1;
+       if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
+-      /* Nothing we can do, no more memory.  */
+-      goto converted;
++      /* Nothing we can do, no more memory.  We cannot use the
++         translation because it might be encoded incorrectly.  */
++      return (char *) -1;
+       if (domain->conv_tab[act] == NULL)
+       {
+@@ -878,8 +886,10 @@ _nl_find_msg (domain_file, domainbinding
+             if (res != __GCONV_FULL_OUTPUT)
+               {
++                /* We should not use the translation at all, it
++                   is incorrectly encoded.  */
+                 __libc_lock_unlock (lock);
+-                goto converted;
++                return NULL;
+               }
+             inbuf = result;
+@@ -905,7 +915,7 @@ _nl_find_msg (domain_file, domainbinding
+             if (errno != E2BIG)
+               {
+                 __libc_lock_unlock (lock);
+-                goto converted;
++                return NULL;
+               }
+ #  endif
+ # endif
+@@ -941,7 +951,7 @@ _nl_find_msg (domain_file, domainbinding
+                 freemem = NULL;
+                 freemem_size = 0;
+                 __libc_lock_unlock (lock);
+-                goto converted;
++                return (char *) -1;
+               }
+ # ifdef _LIBC
+@@ -979,7 +989,6 @@ _nl_find_msg (domain_file, domainbinding
+       resultlen = *(size_t *) domain->conv_tab[act];
+     }
+- converted:
+   /* The result string is converted.  */
+ #endif /* _LIBC || HAVE_ICONV */
diff --git a/src/patches/glibc/glibc-rh197790.patch b/src/patches/glibc/glibc-rh197790.patch
new file mode 100644 (file)
index 0000000..8d4711f
--- /dev/null
@@ -0,0 +1,77 @@
+2006-08-31  Jakub Jelinek  <jakub@redhat.com>
+
+       * malloc/malloc.c (_int_malloc): Use full list insert and not
+       shortcut which assumes the list is empty for large requests
+       too.
+
+2006-08-26  Ulrich Drepper  <drepper@redhat.com>
+
+       * malloc/malloc.c (_int_malloc): Fix test for large enough buffer
+       for early termination.  When no unsorted block matches perfectly
+       and an exiting block has to be split, use full list insert and
+       not shortcut which assumes the list is empty.
+
+2006-08-19  Ulrich Drepper  <drepper@redhat.com>
+
+       * malloc/malloc.c (_int_malloc): Limit number of unsorted blocks
+       to sort in each call.
+
+--- libc/malloc/malloc.c       9 Aug 2006 21:50:30 -0000
++++ libc/malloc/malloc.c       7 Sep 2006 16:06:02 -0000
+@@ -4055,6 +4096,8 @@ _int_malloc(mstate av, size_t bytes)
+   for(;;) {
++    int iters = 0;
++    bool any_larger = false;
+     while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) {
+       bck = victim->bk;
+       if (__builtin_expect (victim->size <= 2 * SIZE_SZ, 0)
+@@ -4150,6 +4193,12 @@ _int_malloc(mstate av, size_t bytes)
+       victim->fd = fwd;
+       fwd->bk = victim;
+       bck->fd = victim;
++
++      if (size >= nb + MINSIZE)
++      any_larger = true;
++#define MAX_ITERS     10000
++      if (++iters >= MAX_ITERS)
++      break;
+     }
+     /*
+@@ -4182,8 +4231,14 @@ _int_malloc(mstate av, size_t bytes)
+         /* Split */
+         else {
+           remainder = chunk_at_offset(victim, nb);
+-          unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
+-          remainder->bk = remainder->fd = unsorted_chunks(av);
++          /* We cannot assume the unsorted list is empty and therefore
++             have to perform a complete insert here.  */
++        bck = unsorted_chunks(av);
++        fwd = bck->fd;
++        remainder->bk = bck;
++        remainder->fd = fwd;
++        bck->fd = remainder;
++        fwd->bk = remainder;
+           set_head(victim, nb | PREV_INUSE |
+                  (av != &main_arena ? NON_MAIN_ARENA : 0));
+           set_head(remainder, remainder_size | PREV_INUSE);
+@@ -4268,8 +4323,15 @@ _int_malloc(mstate av, size_t bytes)
+         else {
+           remainder = chunk_at_offset(victim, nb);
+-          unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
+-          remainder->bk = remainder->fd = unsorted_chunks(av);
++        /* We cannot assume the unsorted list is empty and therefore
++           have to perform a complete insert here.  */
++        bck = unsorted_chunks(av);
++        fwd = bck->fd;
++        remainder->bk = bck;
++        remainder->fd = fwd;
++        bck->fd = remainder;
++        fwd->bk = remainder;
++
+           /* advertise as last remainder */
+           if (in_smallbin_range(nb))
+             av->last_remainder = remainder;
diff --git a/src/patches/glibc/glibc-rh197932.patch b/src/patches/glibc/glibc-rh197932.patch
new file mode 100644 (file)
index 0000000..078d761
--- /dev/null
@@ -0,0 +1,93 @@
+2006-07-26  Gavin Romig-Koch  <gavin@redhat.com>
+
+       * stdlib/cxa_atexit.c (__new_exitfn_called): New variable.
+       (__new_exitfn): Bump it in every successful call.
+       * stdlib/cxa_finalize.c (__cxa_finalize): If destructor registered
+       more exit handlers, call them right away.
+       * stdlib/exit.h: Declare __new_exitfn_called.
+
+2006-07-25  Ulrich Drepper  <drepper@redhat.com>
+
+       * stdlib/cxa_finalize.c (__cxa_finalize): Fix race condition when
+       calling registered handler.
+
+--- libc/stdlib/cxa_atexit.c   18 Dec 2005 17:30:24 -0000      1.7
++++ libc/stdlib/cxa_atexit.c   26 Jul 2006 07:24:45 -0000      1.8
+@@ -48,6 +48,7 @@ __libc_lock_define_initialized (static, 
+ static struct exit_function_list initial;
+ struct exit_function_list *__exit_funcs = &initial;
++uint64_t __new_exitfn_called;
+ struct exit_function *
+ __new_exitfn (void)
+@@ -88,7 +89,10 @@ __new_exitfn (void)
+   /* Mark entry as used, but we don't know the flavor now.  */
+   if (l != NULL)
+-    l->fns[i].flavor = ef_us;
++    {
++      l->fns[i].flavor = ef_us;
++      ++__new_exitfn_called;
++    }
+   __libc_lock_unlock (lock);
+--- libc/stdlib/cxa_finalize.c 18 Dec 2005 17:31:14 -0000      1.9
++++ libc/stdlib/cxa_finalize.c 26 Jul 2006 07:25:44 -0000      1.12
+@@ -30,16 +30,33 @@ __cxa_finalize (void *d)
+ {
+   struct exit_function_list *funcs;
++ restart:
+   for (funcs = __exit_funcs; funcs; funcs = funcs->next)
+     {
+       struct exit_function *f;
+       for (f = &funcs->fns[funcs->idx - 1]; f >= &funcs->fns[0]; --f)
+-      if ((d == NULL || d == f->func.cxa.dso_handle)
+-          /* We don't want to run this cleanup more than once.  */
+-          && ! atomic_compare_and_exchange_bool_acq (&f->flavor, ef_free,
+-                                                     ef_cxa))
+-        (*f->func.cxa.fn) (f->func.cxa.arg, 0);
++      {
++        void (*cxafn) (void *arg, int status);
++        void *cxaarg;
++
++        if ((d == NULL || d == f->func.cxa.dso_handle)
++            /* We don't want to run this cleanup more than once.  */
++            && (cxafn = f->func.cxa.fn,
++                cxaarg = f->func.cxa.arg,
++                ! atomic_compare_and_exchange_bool_acq (&f->flavor, ef_free,
++                                                        ef_cxa)))
++          {
++            uint64_t check = __new_exitfn_called;
++
++            cxafn (cxaarg, 0);
++
++            /* It is possible that that last exit function registered
++               more exit functions.  Start the loop over.  */
++            if (__builtin_expect (check != __new_exitfn_called, 0))
++              goto restart;
++          }
++      }
+     }
+   /* Remove the registered fork handlers.  We do not have to
+--- libc/stdlib/exit.h 12 Mar 2002 18:47:24 -0000      1.10
++++ libc/stdlib/exit.h 26 Jul 2006 07:23:43 -0000      1.11
+@@ -19,6 +20,7 @@
+ #ifndef       _EXIT_H
+ #define _EXIT_H 1
++#include <stdint.h>
+ enum
+ {
+@@ -59,5 +61,6 @@ struct exit_function_list
+ extern struct exit_function_list *__exit_funcs attribute_hidden;
+ extern struct exit_function *__new_exitfn (void);
++extern uint64_t __new_exitfn_called attribute_hidden;
+ #endif        /* exit.h  */
diff --git a/src/patches/glibc/glibc-rh201748.patch b/src/patches/glibc/glibc-rh201748.patch
new file mode 100644 (file)
index 0000000..c562076
--- /dev/null
@@ -0,0 +1,18 @@
+2006-08-08  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/ia64/bits/fcntl.h (O_DIRECT): Protect with
+       __USE_GNU.
+
+--- libc/sysdeps/unix/sysv/linux/ia64/bits/fcntl.h     26 Jul 2006 01:27:05 -0000      1.14
++++ libc/sysdeps/unix/sysv/linux/ia64/bits/fcntl.h     8 Aug 2006 18:28:06 -0000       1.15
+@@ -43,9 +43,9 @@
+ #define O_SYNC                010000
+ #define O_FSYNC               O_SYNC
+ #define O_ASYNC               020000
+-#define O_DIRECT      040000
+ #ifdef __USE_GNU
++# define O_DIRECT     040000
+ # define O_DIRECTORY  0200000 /* must be a directory */
+ # define O_NOFOLLOW   0400000 /* don't follow links */
+ # define O_NOATIME    01000000 /* Do not set atime.  */
diff --git a/src/patches/glibc/glibc-rh201826.patch b/src/patches/glibc/glibc-rh201826.patch
new file mode 100644 (file)
index 0000000..2fbcc20
--- /dev/null
@@ -0,0 +1,24 @@
+2006-08-09  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/nice.c (nice): Transform EACCES errno from setpriority
+       to EPERM.
+
+--- libc/sysdeps/unix/nice.c   28 Sep 2002 19:13:13 -0000      1.6
++++ libc/sysdeps/unix/nice.c   15 Aug 2006 05:24:45 -0000      1.7
+@@ -47,9 +47,11 @@ nice (int incr)
+   else if (prio >= PRIO_MAX)
+     prio = PRIO_MAX - 1;
+   result = setpriority (PRIO_PROCESS, 0, prio);
+-  if (result != -1)
+-    return getpriority (PRIO_PROCESS, 0);
+-  else
+-    return -1;
+-
++  if (result == -1)
++    {
++      if (errno == EACCES)
++      errno = EPERM;
++      return -1;
++    }
++  return getpriority (PRIO_PROCESS, 0);
+ }
diff --git a/src/patches/glibc/glibc-rh202991.patch b/src/patches/glibc/glibc-rh202991.patch
new file mode 100644 (file)
index 0000000..cb61a8e
--- /dev/null
@@ -0,0 +1,207 @@
+2006-09-06  Jakub Jelinek  <jakub@redhat.com>
+
+       * posix/regex_internal.c (re_string_reconstruct): Handle
+       offset < pstr->valid_raw_len && pstr->offsets_needed case.
+       Ensure no bytes read before raw_mbs array.  Pass a saved copy of
+       pstr->valid_len - 1 rather than pstr->valid_raw_len - 1 to
+       re_string_context_at.
+       * posix/Makefile: Add rules to build and run bug-regex26 test.
+       * posix/bug-regex26.c: New test.
+
+--- libc/posix/Makefile        2 Aug 2006 16:43:46 -0000       1.192
++++ libc/posix/Makefile        7 Sep 2006 13:50:05 -0000       1.193
+@@ -81,7 +81,7 @@ tests                := tstgetopt testfnm runtests run
+                  bug-regex13 bug-regex14 bug-regex15 bug-regex16 \
+                  bug-regex17 bug-regex18 bug-regex19 bug-regex20 \
+                  bug-regex21 bug-regex22 bug-regex23 bug-regex24 \
+-                 bug-regex25 tst-nice tst-nanosleep tst-regex2 \
++                 bug-regex25 bug-regex26 tst-nice tst-nanosleep tst-regex2 \
+                  transbug tst-rxspencer tst-pcre tst-boost \
+                  bug-ga1 tst-vfork1 tst-vfork2 tst-waitid \
+                  tst-getaddrinfo2 bug-glob1 bug-glob2 tst-sysconf \
+@@ -189,6 +189,7 @@ bug-regex20-ENV = LOCPATH=$(common-objpf
+ bug-regex22-ENV = LOCPATH=$(common-objpfx)localedata
+ bug-regex23-ENV = LOCPATH=$(common-objpfx)localedata
+ bug-regex25-ENV = LOCPATH=$(common-objpfx)localedata
++bug-regex26-ENV = LOCPATH=$(common-objpfx)localedata
+ tst-rxspencer-ARGS = --utf8 rxspencer/tests
+ tst-rxspencer-ENV = LOCPATH=$(common-objpfx)localedata
+ tst-pcre-ARGS = PCRE.tests
+--- libc/posix/bug-regex26.c   1 Jan 1970 00:00:00 -0000
++++ libc/posix/bug-regex26.c   7 Sep 2006 13:49:22 -0000       1.2
+@@ -0,0 +1,38 @@
++/* Test re_search with dotless i.
++   Copyright (C) 2006 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <locale.h>
++#include <regex.h>
++#include <string.h>
++
++int
++main (void)
++{
++  struct re_pattern_buffer r;
++  struct re_registers s;
++  setlocale (LC_ALL, "en_US.UTF-8");
++  memset (&r, 0, sizeof (r));
++  memset (&s, 0, sizeof (s));
++  re_set_syntax (RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE | RE_ICASE);
++  re_compile_pattern ("insert into", 11, &r);
++  re_search (&r, "\xFF\0\x12\xA2\xAA\xC4\xB1,K\x12\xC4\xB1*\xACK",
++           15, 0, 15, &s);
++  return 0;
++}
+--- libc/posix/regex_internal.c        4 Jun 2006 04:57:19 -0000       1.66
++++ libc/posix/regex_internal.c        7 Sep 2006 13:48:12 -0000       1.67
+@@ -601,34 +601,98 @@ re_string_reconstruct (pstr, idx, eflags
+   if (BE (offset != 0, 1))
+     {
+-      /* Are the characters which are already checked remain?  */
+-      if (BE (offset < pstr->valid_raw_len, 1)
+-#ifdef RE_ENABLE_I18N
+-        /* Handling this would enlarge the code too much.
+-           Accept a slowdown in that case.  */
+-        && pstr->offsets_needed == 0
+-#endif
+-       )
++      /* Should the already checked characters be kept?  */
++      if (BE (offset < pstr->valid_raw_len, 1))
+       {
+         /* Yes, move them to the front of the buffer.  */
+-        pstr->tip_context = re_string_context_at (pstr, offset - 1, eflags);
+ #ifdef RE_ENABLE_I18N
+-        if (pstr->mb_cur_max > 1)
+-          memmove (pstr->wcs, pstr->wcs + offset,
+-                   (pstr->valid_len - offset) * sizeof (wint_t));
++        if (BE (pstr->offsets_needed, 0))
++          {
++            int low = 0, high = pstr->valid_len, mid;
++            do
++              {
++                mid = (high + low) / 2;
++                if (pstr->offsets[mid] > offset)
++                  high = mid;
++                else if (pstr->offsets[mid] < offset)
++                  low = mid + 1;
++                else
++                  break;
++              }
++            while (low < high);
++            if (pstr->offsets[mid] < offset)
++              ++mid;
++            pstr->tip_context = re_string_context_at (pstr, mid - 1,
++                                                      eflags);
++            /* This can be quite complicated, so handle specially
++               only the common and easy case where the character with
++               different length representation of lower and upper
++               case is present at or after offset.  */
++            if (pstr->valid_len > offset
++                && mid == offset && pstr->offsets[mid] == offset)
++              {
++                memmove (pstr->wcs, pstr->wcs + offset,
++                         (pstr->valid_len - offset) * sizeof (wint_t));
++                memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset);
++                pstr->valid_len -= offset;
++                pstr->valid_raw_len -= offset;
++                for (low = 0; low < pstr->valid_len; low++)
++                  pstr->offsets[low] = pstr->offsets[low + offset] - offset;
++              }
++            else
++              {
++                /* Otherwise, just find out how long the partial multibyte
++                   character at offset is and fill it with WEOF/255.  */
++                pstr->len = pstr->raw_len - idx + offset;
++                pstr->stop = pstr->raw_stop - idx + offset;
++                pstr->offsets_needed = 0;
++                while (mid > 0 && pstr->offsets[mid - 1] == offset)
++                  --mid;
++                while (mid < pstr->valid_len)
++                  if (pstr->wcs[mid] != WEOF)
++                    break;
++                  else
++                    ++mid;
++                if (mid == pstr->valid_len)
++                  pstr->valid_len = 0;
++                else
++                  {
++                    pstr->valid_len = pstr->offsets[mid] - offset;
++                    if (pstr->valid_len)
++                      {
++                        for (low = 0; low < pstr->valid_len; ++low)
++                          pstr->wcs[low] = WEOF;
++                        memset (pstr->mbs, 255, pstr->valid_len);
++                      }
++                  }
++                pstr->valid_raw_len = pstr->valid_len;
++              }
++          }
++        else
++#endif
++          {
++            pstr->tip_context = re_string_context_at (pstr, offset - 1,
++                                                      eflags);
++#ifdef RE_ENABLE_I18N
++            if (pstr->mb_cur_max > 1)
++              memmove (pstr->wcs, pstr->wcs + offset,
++                       (pstr->valid_len - offset) * sizeof (wint_t));
+ #endif /* RE_ENABLE_I18N */
+-        if (BE (pstr->mbs_allocated, 0))
+-          memmove (pstr->mbs, pstr->mbs + offset,
+-                   pstr->valid_len - offset);
+-        pstr->valid_len -= offset;
+-        pstr->valid_raw_len -= offset;
++            if (BE (pstr->mbs_allocated, 0))
++              memmove (pstr->mbs, pstr->mbs + offset,
++                       pstr->valid_len - offset);
++            pstr->valid_len -= offset;
++            pstr->valid_raw_len -= offset;
+ #if DEBUG
+-        assert (pstr->valid_len > 0);
++            assert (pstr->valid_len > 0);
+ #endif
++          }
+       }
+       else
+       {
+         /* No, skip all characters until IDX.  */
++        int prev_valid_len = pstr->valid_len;
++
+ #ifdef RE_ENABLE_I18N
+         if (BE (pstr->offsets_needed, 0))
+           {
+@@ -652,6 +716,8 @@ re_string_reconstruct (pstr, idx, eflags
+                    byte other than 0x80 - 0xbf.  */
+                 raw = pstr->raw_mbs + pstr->raw_mbs_idx;
+                 end = raw + (offset - pstr->mb_cur_max);
++                if (end < pstr->raw_mbs)
++                  end = pstr->raw_mbs;
+                 for (p = raw + offset - 1; p >= end; --p)
+                   if ((*p & 0xc0) != 0x80)
+                     {
+@@ -688,7 +754,7 @@ re_string_reconstruct (pstr, idx, eflags
+               pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx;
+             if (wc == WEOF)
+               pstr->tip_context
+-                = re_string_context_at (pstr, pstr->valid_raw_len - 1, eflags);
++                = re_string_context_at (pstr, prev_valid_len - 1, eflags);
+             else
+               pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0)
+                                     && IS_WIDE_WORD_CHAR (wc))
diff --git a/src/patches/glibc/glibc-rh203237.patch b/src/patches/glibc/glibc-rh203237.patch
new file mode 100644 (file)
index 0000000..7be81ac
--- /dev/null
@@ -0,0 +1,32 @@
+2006-08-19  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nss_nis/nis-service.c (internal_nis_getservent_r): . If map
+       is empty simply return and use next service.
+       * nis/nss_nis/nis-rpc.c (internal_nis_getrpcent_r): Likewise.
+
+--- libc/nis/nss_nis/nis-rpc.c 29 Apr 2006 01:12:53 -0000      1.21
++++ libc/nis/nss_nis/nis-rpc.c 19 Aug 2006 18:35:44 -0000      1.22
+@@ -117,6 +117,10 @@ internal_nis_getrpcent_r (struct rpcent 
+   if (intern->start == NULL)
+     internal_nis_setrpcent (intern);
++  if (intern->next == NULL)
++    /* Not one entry in the map.  */
++    return NSS_STATUS_NOTFOUND;
++
+   /* Get the next entry until we found a correct one. */
+   do
+     {
+--- libc/nis/nss_nis/nis-service.c     9 May 2006 19:06:22 -0000       1.35
++++ libc/nis/nss_nis/nis-service.c     19 Aug 2006 18:36:25 -0000      1.36
+@@ -188,6 +188,10 @@ internal_nis_getservent_r (struct serven
+   if (intern.start == NULL)
+     internal_nis_setservent ();
++  if (intern.next == NULL)
++    /* Not one entry in the map.  */
++    return NSS_STATUS_NOTFOUND;
++
+   /* Get the next entry until we found a correct one.  */
+   do
+     {
diff --git a/src/patches/glibc/glibc-rh203728.patch b/src/patches/glibc/glibc-rh203728.patch
new file mode 100644 (file)
index 0000000..a60989c
--- /dev/null
@@ -0,0 +1,65 @@
+2007-03-15  Jakub Jelinek  <jakub@redhat.com>
+
+       * locale/programs/ld-ctype.c (find_translit): Return NULL if ctype is
+       NULL.
+
+2006-08-28  Jakub Jelinek  <jakub@redhat.com>
+
+       * locale/programs/ld-ctype.c (translit_flatten): Issue error
+       if other's ctype category was missing.
+       * locale/programs/ld-collate.c (collate_read): Return if
+       copy_locale's collate category is missing.
+
+2006-08-26  Ulrich Drepper  <drepper@redhat.com>
+
+       * locale/programs/ld-ctype.c (ctype_read): Better patch for read
+       failure.
+
+2006-08-24  Ulrich Drepper  <drepper@redhat.com>
+
+       * locale/programs/ld-ctype.c (ctype_read): If CTYPE is NULL, don't
+       do anything.
+
+--- libc/locale/programs/ld-collate.c  7 Dec 2005 05:47:27 -0000       1.107
++++ libc/locale/programs/ld-collate.c  28 Aug 2006 16:17:10 -0000      1.108
+@@ -2671,6 +2671,9 @@ collate_read (struct linereader *ldfile,
+             if (locfile_read (copy_locale, charmap) != 0)
+               goto skip_category;
+           }
++
++        if (copy_locale->categories[LC_COLLATE].collate == NULL)
++          return;
+       }
+       lr_ignore_rest (ldfile, 1);
+--- libc/locale/programs/ld-ctype.c    12 Aug 2006 20:19:14 -0000
++++ libc/locale/programs/ld-ctype.c    17 Mar 2007 16:52:21 -0000
+@@ -1866,6 +1866,9 @@ find_translit (struct localedef_t *local
+   assert (locale != NULL);
+   ctype = locale->categories[LC_CTYPE].ctype;
++  if (ctype == NULL)
++    return NULL;
++
+   if (ctype->translit != NULL)
+     result = find_translit2 (ctype, charmap, wch);
+@@ -2245,6 +2248,9 @@ ctype_read (struct linereader *ldfile, s
+             if (locfile_read (copy_locale, charmap) != 0)
+               goto skip_category;
+           }
++
++        if (copy_locale->categories[LC_CTYPE].ctype == NULL)
++          return;
+       }
+       lr_ignore_rest (ldfile, 1);
+@@ -3766,7 +3772,7 @@ translit_flatten (struct locale_ctype_t 
+       other = find_locale (LC_CTYPE, copy_locale, copy_repertoire, charmap);
+-      if (other == NULL)
++      if (other == NULL || other->categories[LC_CTYPE].ctype == NULL)
+       {
+         WITH_CUR_LOCALE (error (0, 0, _("\
+ %s: transliteration data from locale `%s' not available"),
diff --git a/src/patches/glibc/glibc-rh203915.patch b/src/patches/glibc/glibc-rh203915.patch
new file mode 100644 (file)
index 0000000..d96391e
--- /dev/null
@@ -0,0 +1,69 @@
+2006-08-24  Jakub Jelinek  <jakub@redhat.com>
+
+       * malloc/malloc.c (sYSMALLOc): Avoid infinite loop if MMAP
+       keeps failing and heap growth or new heap creation isn't
+       successful either.
+       * malloc/tst-malloc.c (main): Add new tests.
+
+--- libc/malloc/malloc.c       9 Aug 2006 21:50:30 -0000       1.159
++++ libc/malloc/malloc.c       7 Sep 2006 16:06:02 -0000       1.168
+@@ -2851,6 +2862,7 @@ static Void_t* sYSMALLOc(nb, av) INTERNA
+   unsigned long   sum;            /* for updating stats */
+   size_t          pagemask  = mp_.pagesize - 1;
++  bool            tried_mmap = false;
+ #if HAVE_MMAP
+@@ -2867,12 +2879,14 @@ static Void_t* sYSMALLOc(nb, av) INTERNA
+     char* mm;             /* return value from mmap call*/
++  try_mmap:
+     /*
+       Round up size to nearest page.  For mmapped chunks, the overhead
+       is one SIZE_SZ unit larger than for normal chunks, because there
+       is no following chunk whose prev_size field could be used.
+     */
+     size = (nb + SIZE_SZ + MALLOC_ALIGN_MASK + pagemask) & ~pagemask;
++    tried_mmap = true;
+     /* Don't try if size wraps around 0 */
+     if ((unsigned long)(size) > (unsigned long)(nb)) {
+@@ -2996,6 +3011,9 @@ static Void_t* sYSMALLOc(nb, av) INTERNA
+       set_foot(old_top, (old_size + 2*SIZE_SZ));
+       }
+     }
++    else if (!tried_mmap)
++      /* We can at least try to use to mmap memory.  */
++      goto try_mmap;
+   } else { /* av == main_arena */
+--- libc/malloc/tst-malloc.c   6 Jul 2001 04:55:35 -0000       1.2
++++ libc/malloc/tst-malloc.c   24 Aug 2006 17:30:10 -0000      1.3
+@@ -33,7 +33,7 @@ merror (const char *msg)
+ int
+ main (void)
+ {
+-  void *p;
++  void *p, *q;
+   int save;
+   errno = 0;
+@@ -64,5 +64,15 @@ main (void)
+   if (p != NULL)
+     merror ("realloc (p, 0) failed.");
++  p = malloc (513 * 1024);
++  if (p == NULL)
++    merror ("malloc (513K) failed.");
++
++  q = malloc (-512 * 1024);
++  if (q != NULL)
++    merror ("malloc (-512K) succeeded.");
++
++  free (p);
++
+   return errors != 0;
+ }
diff --git a/src/patches/glibc/glibc-rh204122.patch b/src/patches/glibc/glibc-rh204122.patch
new file mode 100644 (file)
index 0000000..1b77ff9
--- /dev/null
@@ -0,0 +1,98 @@
+2006-08-28  Jakub Jelinek  <jakub@redhat.com>
+
+       * inet/getnameinfo.c (getnameinfo): For AF_INET, check errno
+       only if herrno is NETDB_INTERNAL.  Handle errors other than
+       ERANGE outside of the loops, handle TRY_AGAIN.
+
+--- libc/inet/getnameinfo.c    6 Apr 2006 21:51:24 -0000       1.34
++++ libc/inet/getnameinfo.c    28 Aug 2006 16:23:18 -0000      1.35
+@@ -203,48 +203,40 @@ getnameinfo (const struct sockaddr *sa, 
+       if (!(flags & NI_NUMERICHOST))
+         {
+           struct hostent *h = NULL;
++          if (sa->sa_family == AF_INET6)
++            {
++              while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr),
++                                        sizeof(struct in6_addr),
++                                        AF_INET6, &th, tmpbuf, tmpbuflen,
++                                        &h, &herrno))
++                if (herrno == NETDB_INTERNAL && errno == ERANGE)
++                  tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
++                else
++                  break;
++            }
++          else
++            {
++              while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
++                                        sizeof(struct in_addr), AF_INET,
++                                        &th, tmpbuf, tmpbuflen,
++                                        &h, &herrno))
++                if (herrno == NETDB_INTERNAL && errno == ERANGE)
++                  tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
++                else
++                  break;
++            }
++
+           if (h == NULL)
+             {
+-              if (sa->sa_family == AF_INET6)
++              if (herrno == NETDB_INTERNAL)
+                 {
+-                  while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr),
+-                                            sizeof(struct in6_addr),
+-                                            AF_INET6, &th, tmpbuf, tmpbuflen,
+-                                            &h, &herrno))
+-                    {
+-                      if (herrno == NETDB_INTERNAL)
+-                        {
+-                          if (errno == ERANGE)
+-                            tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
+-                                                    2 * tmpbuflen);
+-                          else
+-                            {
+-                              __set_h_errno (herrno);
+-                              __set_errno (serrno);
+-                              return EAI_SYSTEM;
+-                            }
+-                        }
+-                      else
+-                        {
+-                          break;
+-                        }
+-                    }
++                  __set_h_errno (herrno);
++                  return EAI_SYSTEM;
+                 }
+-              else
++              if (herrno == TRY_AGAIN)
+                 {
+-                  while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
+-                                            sizeof(struct in_addr), AF_INET,
+-                                            &th, tmpbuf, tmpbuflen,
+-                                            &h, &herrno))
+-                    {
+-                      if (errno == ERANGE)
+-                        tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
+-                                                2 * tmpbuflen);
+-                      else
+-                        {
+-                          break;
+-                        }
+-                    }
++                  __set_h_errno (herrno);
++                  return EAI_AGAIN;
+                 }
+             }
+@@ -361,10 +353,7 @@ getnameinfo (const struct sockaddr *sa, 
+                                (const void *) &(((const struct sockaddr_in *) sa)->sin_addr),
+                                host, hostlen);
+               if (c == NULL)
+-                {
+-                  __set_errno (serrno);
+-                  return EAI_SYSTEM;
+-                }
++                return EAI_SYSTEM;
+             }
+           ok = 1;
+         }
diff --git a/src/patches/glibc/glibc-rh205113.patch b/src/patches/glibc/glibc-rh205113.patch
new file mode 100644 (file)
index 0000000..7f50bfe
--- /dev/null
@@ -0,0 +1,42 @@
+2006-09-04  Jakub Jelinek  <jakub@redhat.com>
+
+       * resolv/res_mkquery.c (res_nmkquery): Set hp->id to statp->id after
+       randomization rather than before.
+       * resolv/res_init.c (res_randomid): Don't call gettimeofday here.
+
+--- libc/resolv/res_init.c     1 Nov 2005 00:05:17 -0000       1.43
++++ libc/resolv/res_init.c     4 Sep 2006 17:59:54 -0000       1.44
+@@ -537,10 +537,7 @@ net_mask(in)              /* XXX - should really use
+ u_int
+ res_randomid(void) {
+-      struct timeval now;
+-
+-      __gettimeofday(&now, NULL);
+-      return (0xffff & (now.tv_sec ^ now.tv_usec ^ __getpid()));
++      return 0xffff & __getpid();
+ }
+ #ifdef _LIBC
+ libc_hidden_def (__res_randomid)
+--- libc/resolv/res_mkquery.c  6 May 2006 18:04:12 -0000       1.16
++++ libc/resolv/res_mkquery.c  4 Sep 2006 17:57:02 -0000       1.17
+@@ -124,10 +124,6 @@ res_nmkquery(res_state statp,
+          incremented by one after the initial randomization which
+          still predictable if the application does multiple
+          requests.  */
+-#if 0
+-      hp->id = htons(++statp->id);
+-#else
+-      hp->id = htons(statp->id);
+       int randombits;
+       do
+         {
+@@ -141,7 +137,7 @@ res_nmkquery(res_state statp,
+         }
+       while ((randombits & 0xffff) == 0);
+       statp->id = (statp->id + randombits) & 0xffff;
+-#endif
++      hp->id = htons(statp->id);
+       hp->opcode = op;
+       hp->rd = (statp->options & RES_RECURSE) != 0;
+       hp->rcode = NOERROR;
diff --git a/src/patches/glibc/glibc-rh206483.patch b/src/patches/glibc/glibc-rh206483.patch
new file mode 100644 (file)
index 0000000..5b150fa
--- /dev/null
@@ -0,0 +1,45 @@
+2006-10-10  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_subr.c (nis_getnames): Add trailing dot to NIS_PATH
+       components which lack them.
+
+       * nis/nis_subr.c (nis_getnames): Make sure that we always return
+       at least one entry consisting of the parameter concatenated with
+       the domain.
+
+--- libc/nis/nis_subr.c        16 Jun 2006 22:30:02 -0000      1.15
++++ libc/nis/nis_subr.c        11 Oct 2006 01:27:38 -0000      1.17
+@@ -251,13 +251,16 @@ nis_getnames (const_nis_name name)
+           {
+             char *p;
+-            tmp = malloc (cplen + name_len + 2);
++            tmp = malloc (cplen + name_len + 3);
+             if (__builtin_expect (tmp == NULL, 0))
+               goto free_null;
+-            p = __stpcpy (tmp, name);
++            p = __mempcpy (tmp, name, name_len);
+             *p++ = '.';
+-            memcpy (p, cp, cplen + 1);
++            p = __mempcpy (p, cp, cplen);
++            if (p[-1] != '.')
++              *p++ = '.';
++            *p = '\0';
+           }
+         if (pos >= count)
+@@ -275,6 +278,13 @@ nis_getnames (const_nis_name name)
+       cp = __strtok_r (NULL, ":", &saveptr);
+     }
++  if (pos == 0
++      && __asprintf (&getnames[pos++], "%s%s%s%s",
++                   name, name[name_len - 1] == '.' ? "" : ".",
++                   local_domain,
++                   local_domain[local_domain_len - 1] == '.' ? "" : ".") < 0)
++    goto free_null;
++
+   getnames[pos] = NULL;
+   return getnames;
diff --git a/src/patches/glibc/glibc-rh206639.patch b/src/patches/glibc/glibc-rh206639.patch
new file mode 100644 (file)
index 0000000..357f129
--- /dev/null
@@ -0,0 +1,153 @@
+2006-09-19  Ulrich Drepper  <drepper@redhat.com>
+
+       * elf/dl-close.c (_dl_close): If dependency is not unloaded make
+       sure no reference to the unloaded map's search list remains in the
+       dependency's scope.
+
+2006-09-16  Jakub Jelinek  <jakub@redhat.com>
+
+       * elf/Makefile: Add rules to build and run unload7 test.
+       * elf/unload7.c: New test.
+       * elf/unload7mod1.c: New file.
+       * elf/unload7mod2.c: New file.
+
+--- libc/elf/Makefile  24 Aug 2006 20:19:45 -0000      1.314
++++ libc/elf/Makefile  19 Sep 2006 14:41:41 -0000      1.315
+@@ -87,6 +87,7 @@ distribute   := rtld-Rules \
+                  unload3mod1.c unload3mod2.c unload3mod3.c unload3mod4.c \
+                  unload4mod1.c unload4mod2.c unload4mod3.c unload4mod4.c \
+                  unload6mod1.c unload6mod2.c unload6mod3.c \
++                 unload7mod1.c unload7mod2.c \
+                  order2mod1.c order2mod2.c order2mod3.c order2mod4.c \
+                  tst-leaks1.c
+@@ -160,7 +161,7 @@ tests += loadtest restest1 preloadtest l
+        tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-align \
+        tst-align2 $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \
+        tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
+-       unload3 unload4 unload5 unload6 tst-global1 order2
++       unload3 unload4 unload5 unload6 unload7 tst-global1 order2
+ #      reldep9
+ test-srcs = tst-pathopt
+ tests-vis-yes = vismain
+@@ -200,6 +201,7 @@ modules-names = testobj1 testobj2 testob
+               unload3mod1 unload3mod2 unload3mod3 unload3mod4 \
+               unload4mod1 unload4mod2 unload4mod3 unload4mod4 \
+               unload6mod1 unload6mod2 unload6mod3 \
++              unload7mod1 unload7mod2 \
+               order2mod1 order2mod2 order2mod3 order2mod4
+ ifeq (yes,$(have-initfini-array))
+ modules-names += tst-array2dep
+@@ -440,6 +442,8 @@ $(objpfx)unload4mod2.so: $(objpfx)unload
+ $(objpfx)unload6mod1.so: $(libdl)
+ $(objpfx)unload6mod2.so: $(libdl)
+ $(objpfx)unload6mod3.so: $(libdl)
++$(objpfx)unload7mod1.so: $(libdl)
++$(objpfx)unload7mod2.so: $(objpfx)unload7mod1.so
+ LDFLAGS-tst-tlsmod5.so = -nostdlib
+ LDFLAGS-tst-tlsmod6.so = -nostdlib
+@@ -712,6 +716,10 @@ $(objpfx)unload6: $(libdl)
+ $(objpfx)unload6.out: $(objpfx)unload6mod1.so $(objpfx)unload6mod2.so \
+                     $(objpfx)unload6mod3.so
++$(objpfx)unload7: $(libdl)
++$(objpfx)unload7.out: $(objpfx)unload7mod1.so $(objpfx)unload7mod2.so
++unload7-ENV = MALLOC_PERTURB_=85
++
+ ifdef libdl
+ $(objpfx)tst-tls9-static: $(common-objpfx)dlfcn/libdl.a
+ $(objpfx)tst-tls9-static.out: $(objpfx)tst-tlsmod5.so $(objpfx)tst-tlsmod6.so
+--- libc/elf/dl-close.c        27 Apr 2005 01:32:01 -0000      1.116
++++ libc/elf/dl-close.c        19 Sep 2006 14:39:42 -0000      1.117
+@@ -330,7 +330,7 @@ _dl_close (void *_map)
+             for (cnt = 0; imap->l_scope[cnt] != NULL; ++cnt)
+               /* This relies on l_scope[] entries being always set either
+-                 to its own l_symbolic_searchlist address, or some other map's
++                 to its own l_symbolic_searchlist address, or some map's
+                  l_searchlist address.  */
+               if (imap->l_scope[cnt] != &imap->l_symbolic_searchlist)
+                 {
+@@ -347,6 +347,21 @@ _dl_close (void *_map)
+                     }
+                 }
+           }
++        else
++          {
++            unsigned int cnt = 0;
++            while (imap->l_scope[cnt] != NULL)
++              {
++                if (imap->l_scope[cnt] == &map->l_searchlist)
++                  {
++                    while ((imap->l_scope[cnt] = imap->l_scope[cnt + 1])
++                           != NULL)
++                      ++cnt;
++                    break;
++                  }
++                ++cnt;
++              }
++          }
+         /* The loader is gone, so mark the object as not having one.
+            Note: l_idx != -1 -> object will be removed.  */
+--- libc/elf/unload7.c 1 Jan 1970 00:00:00 -0000
++++ libc/elf/unload7.c 19 Sep 2006 14:41:09 -0000      1.1
+@@ -0,0 +1,39 @@
++#include <dlfcn.h>
++#include <stdio.h>
++
++int
++main (void)
++{
++  void *h = dlopen ("$ORIGIN/unload7mod1.so", RTLD_LAZY);
++  if (h == NULL)
++    {
++      puts ("dlopen unload7mod1.so failed");
++      return 1;
++    }
++
++  int (*fn) (void);
++  fn = dlsym (h, "foo");
++  if (fn == NULL)
++    {
++      puts ("dlsym failed");
++      return 1;
++    }
++
++  int ret = 0;
++  if (fn () == 0)
++    ++ret;
++
++  void *h2 = dlopen ("$ORIGIN/unload7mod2.so", RTLD_LAZY);
++  if (h2 == NULL)
++    {
++      puts ("dlopen unload7mod2.so failed");
++      return 1;
++    }
++  dlclose (h2);
++
++  if (fn () == 0)
++    ++ret;
++
++  dlclose (h);
++  return ret;
++}
+--- libc/elf/unload7mod1.c     1 Jan 1970 00:00:00 -0000
++++ libc/elf/unload7mod1.c     19 Sep 2006 14:41:09 -0000      1.1
+@@ -0,0 +1,11 @@
++#include <dlfcn.h>
++#include <stdio.h>
++
++int
++foo (int i)
++{
++  if (dlsym (RTLD_DEFAULT, "unload7_nonexistent_symbol") == NULL)
++    return 1;
++  puts ("dlsym returned non-NULL");
++  return 0;
++}
+--- libc/elf/unload7mod2.c     1 Jan 1970 00:00:00 -0000
++++ libc/elf/unload7mod2.c     19 Sep 2006 14:41:09 -0000      1.1
+@@ -0,0 +1 @@
++int x;
diff --git a/src/patches/glibc/glibc-rh207928.patch b/src/patches/glibc/glibc-rh207928.patch
new file mode 100644 (file)
index 0000000..469ba65
--- /dev/null
@@ -0,0 +1,89 @@
+2006-10-02  Jakub Jelinek  <jakub@redhat.com>
+
+       * nscd/mem.c (mempool_alloc): Round array size to 16 bytes
+       in oldtotal and newtotal calculation.
+       * nscd/nscd-client.h (struct mapped_database): Add datasize
+       field.
+       * nscd/nscd_helper.c (get_mapping): Initialize datasize field.
+       (__nscd_get_map_ref): Get a new mapping even if mapping's data_size
+       increased.
+       (__nscd_cache_search): Add checks to make sure we never reference
+       data beyond the current mapping.
+
+--- libc/nscd/mem.c    7 Dec 2005 05:47:27 -0000       1.8
++++ libc/nscd/mem.c    2 Oct 2006 16:31:11 -0000       1.9
+@@ -484,10 +484,10 @@ mempool_alloc (struct database_dyn *db, 
+         size_t new_data_size = (db->head->data_size
+                                 + MAX (2 * len, db->head->data_size / 8));
+         size_t oldtotal = (sizeof (struct database_pers_head)
+-                           + db->head->module * sizeof (ref_t)
++                           + roundup (db->head->module * sizeof (ref_t), ALIGN)
+                            + db->head->data_size);
+         size_t newtotal = (sizeof (struct database_pers_head)
+-                           + db->head->module * sizeof (ref_t)
++                           + roundup (db->head->module * sizeof (ref_t), ALIGN)
+                            + new_data_size);
+         if (newtotal > db->max_db_size)
+           {
+--- libc/nscd/nscd-client.h    25 Apr 2006 23:48:55 -0000      1.22
++++ libc/nscd/nscd-client.h    2 Oct 2006 16:32:27 -0000       1.23
+@@ -258,6 +258,7 @@ struct mapped_database
+   const char *data;
+   size_t mapsize;
+   int counter;                /* > 0 indicates it is usable.  */
++  size_t datasize;
+ };
+ #define NO_MAPPING ((struct mapped_database *) -1l)
+--- libc/nscd/nscd_helper.c    25 Apr 2006 23:47:53 -0000      1.16
++++ libc/nscd/nscd_helper.c    2 Oct 2006 16:33:51 -0000       1.17
+@@ -290,6 +290,7 @@ get_mapping (request_type type, const ch
+       newp->data = ((char *) mapping + head.header_size
+                   + roundup (head.module * sizeof (ref_t), ALIGN));
+       newp->mapsize = size;
++      newp->datasize = head.data_size;
+       /* Set counter to 1 to show it is usable.  */
+       newp->counter = 1;
+@@ -340,7 +341,8 @@ __nscd_get_map_ref (request_type type, c
+       /* If not mapped or timestamp not updated, request new map.  */
+       if (cur == NULL
+         || (cur->head->nscd_certainly_running == 0
+-            && cur->head->timestamp + MAPPING_TIMEOUT < time (NULL)))
++            && cur->head->timestamp + MAPPING_TIMEOUT < time (NULL))
++        || cur->head->data_size > cur->datasize)
+       cur = get_mapping (type, name,
+                          (struct mapped_database **) &mapptr->mapped);
+@@ -365,14 +367,18 @@ __nscd_cache_search (request_type type, 
+                    const struct mapped_database *mapped)
+ {
+   unsigned long int hash = __nis_hash (key, keylen) % mapped->head->module;
++  size_t datasize = mapped->datasize;
+   ref_t work = mapped->head->array[hash];
+-  while (work != ENDREF)
++  while (work != ENDREF && work + sizeof (struct hashentry) <= datasize)
+     {
+       struct hashentry *here = (struct hashentry *) (mapped->data + work);
+-      if (type == here->type && keylen == here->len
+-        && memcmp (key, mapped->data + here->key, keylen) == 0)
++      if (type == here->type
++        && keylen == here->len
++        && here->key + here->len <= 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
+@@ -380,8 +386,7 @@ __nscd_cache_search (request_type type, 
+         /* See whether we must ignore the entry or whether something
+            is wrong because garbage collection is in progress.  */
+-        if (dh->usable && ((char *) dh + dh->allocsize
+-                           <= (char *) mapped->head + mapped->mapsize))
++        if (dh->usable && here->packet + dh->allocsize <= datasize)
+           return dh;
+       }
diff --git a/src/patches/glibc/glibc-rh208203.patch b/src/patches/glibc/glibc-rh208203.patch
new file mode 100644 (file)
index 0000000..b204e21
--- /dev/null
@@ -0,0 +1,417 @@
+2006-10-06  Ulrich Drepper  <drepper@redhat.com>
+
+       * nis/nis_table.c (nis_list): If __follow_path fails in the new
+       code, make sure the nis_freeresult call doesn't crash and that the
+       result is reported correctly.
+
+2006-09-27  Jakub Jelinek  <jakub@redhat.com>
+
+       * nis/nis_table.c (nis_list): Handle FOLLOW_PATH | ALL_RESULTS
+       when callback is NULL.
+
+       * nis/Versions (libnss_nisplus): Add
+       _nss_nisplus_initgroups_dyn@@GLIBC_PRIVATE.
+       * nis/Makefile (libnss_nisplus-routines): Add nisplus-initgroups.
+       * nis/nss_nisplus/nisplus-grp.c (tablename_val, tablename_len,
+       _nss_create_tablename): Rename to...
+       (grp_tablename_val, grp_tablename_len, _nss_grp_create_tablename):
+       ... these.  No longer static.
+       (internal_setgrent): Adjust users.
+       (_nss_nisplus_getgrnam_r, _nss_nisplus_getgrgid_r): Likewise.
+       Don't use locking around _nss_grp_create_tablename call.
+       * nis/nss_nisplus/nisplus-initgroups.c: New file.
+
+--- libc/nis/Makefile  14 Apr 2006 05:45:49 -0000      1.32
++++ libc/nis/Makefile  6 Oct 2006 17:47:31 -0000       1.33
+@@ -64,7 +64,7 @@ libnss_nis-routines  := $(addprefix nis-,
+ libnss_nis-inhibit-o  = $(filter-out .os,$(object-suffixes))
+ libnss_nisplus-routines       := $(addprefix nisplus-,$(databases)) nisplus-parser \
+-                         nss-nisplus
++                         nss-nisplus nisplus-initgroups
+ libnss_nisplus-inhibit-o = $(filter-out .os,$(object-suffixes))
+ include ../Rules
+--- libc/nis/Versions  20 May 2006 19:21:52 -0000      1.10
++++ libc/nis/Versions  6 Oct 2006 17:48:37 -0000       1.11
+@@ -125,6 +125,6 @@ libnss_nisplus {
+     _nss_nisplus_setetherent; _nss_nisplus_setgrent; _nss_nisplus_sethostent;
+     _nss_nisplus_setnetent; _nss_nisplus_setnetgrent; _nss_nisplus_setprotoent;
+     _nss_nisplus_setpwent; _nss_nisplus_setrpcent; _nss_nisplus_setservent;
+-    _nss_nisplus_setspent;
++    _nss_nisplus_setspent; _nss_nisplus_initgroups_dyn;
+   }
+ }
+--- libc/nis/nis_table.c       7 Aug 2006 16:01:44 -0000       1.38
++++ libc/nis/nis_table.c       6 Oct 2006 20:31:59 -0000       1.40
+@@ -215,6 +215,7 @@ nis_list (const_nis_name name, unsigned 
+   char *tableptr;
+   char *tablepath = NULL;
+   int first_try = 0; /* Do we try the old binding at first ? */
++  nis_result *allres = NULL;
+   if (res == NULL)
+     return NULL;
+@@ -223,6 +224,7 @@ nis_list (const_nis_name name, unsigned 
+     {
+       status = NIS_BADNAME;
+     err_out:
++      nis_freeresult (allres);
+       memset (res, '\0', sizeof (nis_result));
+       NIS_RES_STATUS (res) = status;
+       return res;
+@@ -349,6 +351,7 @@ nis_list (const_nis_name name, unsigned 
+                   if (names != namebuf)
+                     nis_freenames (names);
+                   nis_free_request (ibreq);
++                  nis_freeresult (allres);
+                   return res;
+                 }
+               if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len)
+@@ -392,6 +395,57 @@ nis_list (const_nis_name name, unsigned 
+                   goto again;
+                 }
+             }
++          else if ((flags & (FOLLOW_PATH | ALL_RESULTS))
++                   == (FOLLOW_PATH | ALL_RESULTS))
++            {
++              if (allres == NULL)
++                {
++                  allres = res;
++                  res = malloc (sizeof (nis_result));
++                  if (res == NULL)
++                    {
++                      res = allres;
++                      allres = NULL;
++                      NIS_RES_STATUS (res) = NIS_NOMEMORY;
++                      goto fail;
++                    }
++                  NIS_RES_STATUS (res) = NIS_RES_STATUS (allres);
++                }
++              else
++                {
++                  nis_object *objects_val
++                    = realloc (NIS_RES_OBJECT (allres),
++                               (NIS_RES_NUMOBJ (allres)
++                                + NIS_RES_NUMOBJ (res))
++                               * sizeof (nis_object));
++                  if (objects_val == NULL)
++                    {
++                      NIS_RES_STATUS (res) = NIS_NOMEMORY;
++                      goto fail;
++                    }
++                  NIS_RES_OBJECT (allres) = objects_val;
++                  memcpy (NIS_RES_OBJECT (allres) + NIS_RES_NUMOBJ (allres),
++                          NIS_RES_OBJECT (res),
++                          NIS_RES_NUMOBJ (res) * sizeof (nis_object));
++                  NIS_RES_NUMOBJ (allres) += NIS_RES_NUMOBJ (res);
++                  NIS_RES_NUMOBJ (res) = 0;
++                  free (NIS_RES_OBJECT (res));
++                  NIS_RES_OBJECT (res) = NULL;
++                  NIS_RES_STATUS (allres) = NIS_RES_STATUS (res);
++                  xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res);
++                }
++              clnt_status = __follow_path (&tablepath, &tableptr, ibreq,
++                                           &bptr);
++              if (clnt_status != NIS_SUCCESS)
++                {
++                  /* Prepare for the nis_freeresult call.  */
++                  memset (res, '\0', sizeof (*res));
++
++                  if (clnt_status == NIS_NOMEMORY)
++                    NIS_RES_STATUS (allres) = clnt_status;
++                  ++done;
++                }
++            }
+           else
+             ++done;
+           break;
+@@ -485,6 +539,12 @@ nis_list (const_nis_name name, unsigned 
+   nis_free_request (ibreq);
++  if (allres)
++    {
++      nis_freeresult (res);
++      return allres;
++    }
++
+   return res;
+ }
+ libnsl_hidden_def (nis_list)
+--- libc/nis/nss_nisplus/nisplus-grp.c 20 May 2006 19:20:19 -0000      1.20
++++ libc/nis/nss_nisplus/nisplus-grp.c 6 Oct 2006 17:46:31 -0000       1.21
+@@ -46,13 +46,13 @@ static char *tableptr;
+ static netobj cursor;
+-static nis_name tablename_val;
+-static size_t tablename_len;
++nis_name grp_tablename_val attribute_hidden;
++size_t grp_tablename_len attribute_hidden;
+-static enum nss_status
+-_nss_create_tablename (int *errnop)
++enum nss_status
++_nss_grp_create_tablename (int *errnop)
+ {
+-  if (tablename_val == NULL)
++  if (grp_tablename_val == NULL)
+     {
+       const char *local_dir = nis_local_directory ();
+       size_t local_dir_len = strlen (local_dir);
+@@ -67,11 +67,16 @@ _nss_create_tablename (int *errnop)
+       memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
+-      tablename_len = sizeof (prefix) - 1 + local_dir_len;
++      grp_tablename_len = sizeof (prefix) - 1 + local_dir_len;
+       atomic_write_barrier ();
+-      tablename_val = p;
++      if (atomic_compare_and_exchange_bool_acq (&grp_tablename_val, p, NULL))
++      {
++        /* Another thread already installed the value.  */
++        free (p);
++        grp_tablename_len = strlen (grp_tablename_val);
++      }
+     }
+   return NSS_STATUS_SUCCESS;
+@@ -103,19 +108,19 @@ internal_setgrent (int *errnop)
+ {
+   enum nss_status status = NSS_STATUS_SUCCESS;
+-  if (tablename_val == NULL)
+-    status = _nss_create_tablename (errnop);
++  if (grp_tablename_val == NULL)
++    status = _nss_grp_create_tablename (errnop);
+   if (status == NSS_STATUS_SUCCESS)
+     {
+-      ibreq = __create_ib_request (tablename_val, 0);
++      ibreq = __create_ib_request (grp_tablename_val, 0);
+       if (ibreq == NULL)
+       {
+         *errnop = errno;
+         return NSS_STATUS_TRYAGAIN;
+       }
+-      nis_error retcode = __prepare_niscall (tablename_val, &dir, &bptr, 0);
++      nis_error retcode = __prepare_niscall (grp_tablename_val, &dir, &bptr, 0);
+       if (retcode != NIS_SUCCESS)
+       {
+         nis_free_request (ibreq);
+@@ -285,13 +290,9 @@ _nss_nisplus_getgrnam_r (const char *nam
+ {
+   int parse_res;
+-  if (tablename_val == NULL)
++  if (grp_tablename_val == NULL)
+     {
+-      __libc_lock_lock (lock);
+-
+-      enum nss_status status = _nss_create_tablename (errnop);
+-
+-      __libc_lock_unlock (lock);
++      enum nss_status status = _nss_grp_create_tablename (errnop);
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+@@ -304,10 +305,10 @@ _nss_nisplus_getgrnam_r (const char *nam
+     }
+   nis_result *result;
+-  char buf[strlen (name) + 9 + tablename_len];
++  char buf[strlen (name) + 9 + grp_tablename_len];
+   int olderr = errno;
+-  snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
++  snprintf (buf, sizeof (buf), "[name=%s],%s", name, grp_tablename_val);
+   result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
+@@ -348,13 +349,9 @@ enum nss_status
+ _nss_nisplus_getgrgid_r (const gid_t gid, struct group *gr,
+                        char *buffer, size_t buflen, int *errnop)
+ {
+-  if (tablename_val == NULL)
++  if (grp_tablename_val == NULL)
+     {
+-      __libc_lock_lock (lock);
+-
+-      enum nss_status status = _nss_create_tablename (errnop);
+-
+-      __libc_lock_unlock (lock);
++      enum nss_status status = _nss_grp_create_tablename (errnop);
+       if (status != NSS_STATUS_SUCCESS)
+       return status;
+@@ -362,11 +359,11 @@ _nss_nisplus_getgrgid_r (const gid_t gid
+   int parse_res;
+   nis_result *result;
+-  char buf[8 + 3 * sizeof (unsigned long int) + tablename_len];
++  char buf[8 + 3 * sizeof (unsigned long int) + grp_tablename_len];
+   int olderr = errno;
+   snprintf (buf, sizeof (buf), "[gid=%lu],%s",
+-          (unsigned long int) gid, tablename_val);
++          (unsigned long int) gid, grp_tablename_val);
+   result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+--- libc/nis/nss_nisplus/nisplus-initgroups.c  1 Jan 1970 00:00:00 -0000
++++ libc/nis/nss_nisplus/nisplus-initgroups.c  6 Oct 2006 17:45:26 -0000       1.1
+@@ -0,0 +1,150 @@
++/* Copyright (C) 1997, 2001, 2002, 2003, 2005, 2006
++   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 <atomic.h>
++#include <nss.h>
++#include <grp.h>
++#include <ctype.h>
++#include <errno.h>
++#include <string.h>
++#include <bits/libc-lock.h>
++#include <rpcsvc/nis.h>
++
++#include "nss-nisplus.h"
++#include "nisplus-parser.h"
++#include <libnsl.h>
++#include <nis_intern.h>
++#include <nis_xdr.h>
++
++#define NISOBJVAL(col, obj) \
++  ((obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
++
++#define NISOBJLEN(col, obj) \
++  ((obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
++
++extern nis_name grp_tablename_val attribute_hidden;
++extern size_t grp_tablename_len attribute_hidden;
++extern enum nss_status _nss_grp_create_tablename (int *errnop);
++
++
++enum nss_status
++_nss_nisplus_initgroups_dyn (const char *user, gid_t group, long int *start,
++                           long int *size, gid_t **groupsp, long int limit,
++                           int *errnop)
++{
++  if (grp_tablename_val == NULL)
++    {
++      enum nss_status status = _nss_grp_create_tablename (errnop);
++
++      if (status != NSS_STATUS_SUCCESS)
++      return status;
++    }
++
++  nis_result *result;
++  char buf[strlen (user) + 12 + grp_tablename_len];
++
++  snprintf (buf, sizeof (buf), "[members=%s],%s", user, grp_tablename_val);
++
++  result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH | ALL_RESULTS, NULL, NULL);
++
++  if (result == NULL)
++    {
++      *errnop = ENOMEM;
++      return NSS_STATUS_TRYAGAIN;
++    }
++
++  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
++    {
++      enum nss_status status = niserr2nss (result->status);
++
++      nis_freeresult (result);
++      return status;
++    }
++
++  if (NIS_RES_NUMOBJ (result) == 0)
++    {
++    errout:
++      nis_freeresult (result);
++      return NSS_STATUS_NOTFOUND;
++    }
++
++  gid_t *groups = *groupsp;
++  nis_object *obj = NIS_RES_OBJECT (result);
++  for (unsigned int cnt = 0; cnt < NIS_RES_NUMOBJ (result); ++cnt, ++obj)
++    {
++      if (__type_of (obj) != NIS_ENTRY_OBJ
++        || strcmp (obj->EN_data.en_type, "group_tbl") != 0
++        || obj->EN_data.en_cols.en_cols_len < 4)
++      continue;
++
++      char *numstr = NISOBJVAL (2, obj);
++      size_t len = NISOBJLEN (2, obj);
++      if (len == 0 || numstr[0] == '\0')
++      continue;
++
++      gid_t gid;
++      char *endp;
++      if (__builtin_expect (numstr[len - 1] != '\0', 0))
++      {
++        char numstrbuf[len + 1];
++        memcpy (numstrbuf, numstr, len);
++        numstrbuf[len] = '\0';
++        gid = strtoul (numstrbuf, &endp, 10);
++        if (*endp)
++          continue;
++      }
++      else
++      {
++        gid = strtoul (numstr, &endp, 10);
++        if (*endp)
++          continue;
++      }
++
++      if (gid == group)
++      continue;
++
++      /* Insert this group.  */
++      if (*start == *size)
++      {
++        /* Need a bigger buffer.  */
++        long int newsize;
++
++        if (limit > 0 && *size == limit)
++          /* We reached the maximum.  */
++          break;
++
++        if (limit <= 0)
++          newsize = 2 * *size;
++        else
++          newsize = MIN (limit, 2 * *size);
++
++        gid_t *newgroups = realloc (groups, newsize * sizeof (*groups));
++        if (newgroups == NULL)
++          goto errout;
++        *groupsp = groups = newgroups;
++        *size = newsize;
++      }
++
++      groups[*start] = gid;
++      *start += 1;
++    }
++
++  nis_freeresult (result);
++  return NSS_STATUS_SUCCESS;
++}
diff --git a/src/patches/glibc/glibc-rh210748-workaround.patch b/src/patches/glibc/glibc-rh210748-workaround.patch
new file mode 100644 (file)
index 0000000..fd9489d
--- /dev/null
@@ -0,0 +1,80 @@
+2007-01-15  Jakub Jelinek  <jakub@redhat.com>
+
+       * elf/dl-open.c (add_to_global): If the main searchlist is 256
+       entries or more, on each reallocation at least double the size
+       of the search list rather than growing it linearly.
+       (dl_open_worker): When changing from l_scope_mem to malloced
+       l_scope, start with 64 entries rather than 4.
+
+       * pthread_create.c (__pthread_create_2_1): On the first pthread_create
+       in a process make sure main search list can store at least 256
+       entries.
+
+--- libc/elf/dl-open.c 2006-08-31 08:53:29.000000000 +0200
++++ libc/elf/dl-open.c 2007-01-15 11:22:54.000000000 +0100
+@@ -125,14 +125,18 @@ add_to_global (struct link_map *new)
+     {
+       /* We have to extend the existing array of link maps in the
+        main map.  */
++      size_t new_size = GL(dl_ns)[new->l_ns]._ns_global_scope_alloc;
++      if (new_size >= 256 && new_size > to_add + 8)
++      new_size *= 2;
++      else
++      new_size += to_add + 8;
+       new_global = (struct link_map **)
+       realloc (GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list,
+-               ((GL(dl_ns)[new->l_ns]._ns_global_scope_alloc + to_add + 8)
+-                * sizeof (struct link_map *)));
++               new_size * sizeof (struct link_map *));
+       if (new_global == NULL)
+       goto nomem;
+-      GL(dl_ns)[new->l_ns]._ns_global_scope_alloc += to_add + 8;
++      GL(dl_ns)[new->l_ns]._ns_global_scope_alloc = new_size;
+       GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list = new_global;
+     }
+@@ -396,6 +401,10 @@ dl_open_worker (void *a)
+             if (imap->l_scope == imap->l_scope_mem)
+               {
++                /* Hack: try to minimize the number of realloc calls
++                   when we don't have proper locking yet.  */
++                new_size = 64;
++
+                 newp = (struct r_scope_elem **)
+                   malloc (new_size * sizeof (struct r_scope_elem *));
+                 if (newp == NULL)
+--- libc/nptl/pthread_create.c 2006-09-07 11:04:05.000000000 +0200
++++ libc/nptl/pthread_create.c 2007-01-15 11:18:49.000000000 +0100
+@@ -462,6 +462,30 @@ __pthread_create_2_1 (newthread, attr, s
+   pd->flags = ((iattr->flags & ~(ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET))
+              | (self->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)));
++  /* Hack: realloc the main search list on the first pthread_create call
++     to minimize the number of global search scope reallocations.
++     Wastes at most 1KB on 32-bit and 2KB on 64-bit per process
++     which calls pthread_create.  */
++  if (__builtin_expect (self->header.multiple_threads == 0, 0)
++      && GL(dl_ns)[0]._ns_main_searchlist
++      && GL(dl_ns)[0]._ns_main_searchlist->r_nlist < 256
++      && GL(dl_ns)[0]._ns_global_scope_alloc < 256)
++    {
++      struct link_map **new_global = (struct link_map **)
++      realloc (GL(dl_ns)[0]._ns_global_scope_alloc == 0
++               ? NULL : GL(dl_ns)[0]._ns_main_searchlist->r_list,
++               256 * sizeof (struct link_map *));
++      if (new_global != NULL)
++      {
++        if (GL(dl_ns)[0]._ns_global_scope_alloc == 0)
++          memcpy (new_global, GL(dl_ns)[0]._ns_main_searchlist->r_list,
++                  GL(dl_ns)[0]._ns_main_searchlist->r_nlist
++                  * sizeof (struct link_map *));
++        GL(dl_ns)[0]._ns_global_scope_alloc = 256;
++        GL(dl_ns)[0]._ns_main_searchlist->r_list = new_global;
++      }
++    }
++
+   /* Initialize the field for the ID of the thread which is waiting
+      for us.  This is a self-reference in case the thread is created
+      detached.  */
diff --git a/src/patches/glibc/glibc-rh211116.patch b/src/patches/glibc/glibc-rh211116.patch
new file mode 100644 (file)
index 0000000..e6ff0ca
--- /dev/null
@@ -0,0 +1,157 @@
+2006-10-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * sunrpc/xdr_mem.c (xdrmem_setpos): Don't compare addresses
+       as signed longs, check for x_base + pos overflow.
+       * sunrpc/Makefile (tests): Add tst-xdrmem2.
+       * sunrpc/tst-xdrmem2.c: New test.
+
+--- libc/sunrpc/xdr_mem.c      16 Dec 2002 10:25:27 -0000      1.15
++++ libc/sunrpc/xdr_mem.c      18 Oct 2006 19:25:01 -0000      1.16
+@@ -177,13 +177,15 @@ xdrmem_setpos (xdrs, pos)
+ {
+   caddr_t newaddr = xdrs->x_base + pos;
+   caddr_t lastaddr = xdrs->x_private + xdrs->x_handy;
++  size_t handy = lastaddr - newaddr;
+-  if ((long) newaddr > (long) lastaddr
+-      || (UINT_MAX < LONG_MAX
+-        && (long) UINT_MAX < (long) lastaddr - (long) newaddr))
++  if (newaddr > lastaddr
++      || newaddr < xdrs->x_base
++      || handy != (u_int) handy)
+     return FALSE;
++
+   xdrs->x_private = newaddr;
+-  xdrs->x_handy = (long) lastaddr - (long) newaddr;
++  xdrs->x_handy = (u_int) handy;
+   return TRUE;
+ }
+--- libc/sunrpc/Makefile       26 Jun 2005 18:24:19 -0000      1.84
++++ libc/sunrpc/Makefile       18 Oct 2006 19:25:38 -0000      1.85
+@@ -85,7 +85,7 @@ all: # Make this the default target; it 
+ include ../Makeconfig
+-tests = tst-xdrmem
++tests = tst-xdrmem tst-xdrmem2
+ xtests := tst-getmyaddr
+ ifeq ($(have-thread-library),yes)
+--- libc/sunrpc/tst-xdrmem2.c  1 Jan 1970 00:00:00 -0000
++++ libc/sunrpc/tst-xdrmem2.c  18 Oct 2006 19:24:16 -0000      1.1
+@@ -0,0 +1,114 @@
++/* Copyright (C) 2006 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <limits.h>
++#include <stdio.h>
++#include <string.h>
++#include <rpc/rpc.h>
++#include <sys/mman.h>
++#include <unistd.h>
++
++static int
++do_test (void)
++{
++  XDR xdrs;
++  void *buf;
++  size_t ps = sysconf (_SC_PAGESIZE);
++  uintptr_t half = -1;
++  int v_int;
++  u_short v_u_short;
++
++  half = (half >> 1) & ~(uintptr_t) (ps - 1);
++  buf = mmap ((void *) half, 2 * ps, PROT_READ | PROT_WRITE,
++            MAP_PRIVATE | MAP_ANON, -1, 0);
++  if (buf == MAP_FAILED || buf != (void *) half)
++    {
++      puts ("Couldn't mmap 2 pages in the middle of address space");
++      return 0;
++    }
++
++  xdrmem_create (&xdrs, (char *) buf, 2 * ps, XDR_ENCODE);
++
++#define T(type, val) \
++  v_##type = val;                     \
++  if (! xdr_##type (&xdrs, &v_##type))        \
++    {                                 \
++      puts ("encoding of " #type      \
++          " " #val " failed");        \
++      return 1;                               \
++    }
++
++  T(int, 127)
++
++  u_int pos = xdr_getpos (&xdrs);
++
++  T(u_short, 31)
++
++  if (! xdr_setpos (&xdrs, pos))
++    {
++      puts ("xdr_setpos during encoding failed");
++      return 1;
++    }
++
++  T(u_short, 36)
++
++#undef T
++
++  xdr_destroy (&xdrs);
++
++  xdrmem_create (&xdrs, (char *) buf, 2 * ps, XDR_DECODE);
++
++#define T(type, val) \
++  v_##type = 0x15;                    \
++  if (! xdr_##type (&xdrs, &v_##type))        \
++    {                                 \
++      puts ("decoding of " #type      \
++          " " #val " failed");        \
++      return 1;                               \
++    }                                 \
++  if (v_##type != val)                        \
++    {                                 \
++      puts ("decoded value differs, " \
++          "type " #type " " #val);    \
++      return 1;                               \
++    }
++
++  T(int, 127)
++
++  pos = xdr_getpos (&xdrs);
++
++  T(u_short, 36)
++
++  if (! xdr_setpos (&xdrs, pos))
++    {
++      puts ("xdr_setpos during encoding failed");
++      return 1;
++    }
++
++  T(u_short, 36)
++
++#undef T
++
++  xdr_destroy (&xdrs);
++
++  return 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-rh215572.patch b/src/patches/glibc/glibc-rh215572.patch
new file mode 100644 (file)
index 0000000..17f2b3a
--- /dev/null
@@ -0,0 +1,18 @@
+2006-11-14  Jakub Jelinek  <jakub@redhat.com>
+
+       * nss/nss_files/files-alias.c (get_next_alias): Set line back
+       to first_unused after parsing :include: file.
+
+--- libc/nss/nss_files/files-alias.c   1 Sep 2002 12:38:05 -0000       1.15
++++ libc/nss/nss_files/files-alias.c   15 Nov 2006 22:23:20 -0000      1.16
+@@ -298,8 +298,8 @@ get_next_alias (const char *match, struc
+                         first_unused[room_left - 1] = '\0';
+                         strncpy (first_unused, old_line, room_left);
+-                        if (old_line != NULL)
+-                          free (old_line);
++                        free (old_line);
++                        line = first_unused;
+                         if (first_unused[room_left - 1] != '\0')
+                           goto no_more_room;
diff --git a/src/patches/glibc/glibc-rh218782.patch b/src/patches/glibc/glibc-rh218782.patch
new file mode 100644 (file)
index 0000000..45b5c3f
--- /dev/null
@@ -0,0 +1,50 @@
+2006-12-09  Jakub Jelinek  <jakub@redhat.com>
+
+       * misc/getusershell.c (initshells): Check for integer overflows.
+       Make strings buffer one bigger as fgets always succeeds when second
+       argument is 1.  Don't use calloc for shells array.  Disallow
+       / as shell.
+
+--- libc/misc/getusershell.c   15 May 2006 18:56:36 -0000      1.16
++++ libc/misc/getusershell.c   9 Dec 2006 22:25:00 -0000       1.17
+@@ -92,7 +92,7 @@ initshells()
+       register char **sp, *cp;
+       register FILE *fp;
+       struct stat64 statb;
+-      int flen;
++      size_t flen;
+       if (shells != NULL)
+               free(shells);
+@@ -106,11 +106,15 @@ initshells()
+               (void)fclose(fp);
+               return (char **) okshells;
+       }
+-      if ((strings = malloc((u_int)statb.st_size + 1)) == NULL) {
++      if (statb.st_size > ~(size_t)0 / sizeof (char *) * 3) {
++              (void)fclose(fp);
++              return (char **) okshells;
++      }
++      if ((strings = malloc(statb.st_size + 2)) == NULL) {
+               (void)fclose(fp);
+               return (char **) okshells;
+       }
+-      shells = calloc((unsigned)statb.st_size / 3, sizeof (char *));
++      shells = malloc(statb.st_size / 3 * sizeof (char *));
+       if (shells == NULL) {
+               (void)fclose(fp);
+               free(strings);
+@@ -121,11 +125,11 @@ initshells()
+       __fsetlocking (fp, FSETLOCKING_BYCALLER);
+       sp = shells;
+       cp = strings;
+-      flen = statb.st_size;
++      flen = statb.st_size + 2;
+       while (fgets_unlocked(cp, flen - (cp - strings), fp) != NULL) {
+               while (*cp != '#' && *cp != '/' && *cp != '\0')
+                       cp++;
+-              if (*cp == '#' || *cp == '\0')
++              if (*cp == '#' || *cp == '\0' || cp[1] == '\0')
+                       continue;
+               *sp++ = cp;
+               while (!isspace(*cp) && *cp != '#' && *cp != '\0')
diff --git a/src/patches/glibc/glibc-rh218802.patch b/src/patches/glibc/glibc-rh218802.patch
new file mode 100644 (file)
index 0000000..6d146e7
--- /dev/null
@@ -0,0 +1,82 @@
+2006-12-09  Jakub Jelinek  <jakub@redhat.com>
+
+       * misc/mntent_r.c (__hasmntopt): Check p[optlen] even when p == rest.
+       Start searching for next comma at p rather than rest.
+       * misc/Makefile (tests): Add tst-mntent2.
+       * misc/tst-mntent2.c: New test.
+
+--- libc/misc/Makefile 17 Jun 2006 17:00:58 -0000      1.119
++++ libc/misc/Makefile 9 Dec 2006 22:06:40 -0000       1.120
+@@ -76,7 +76,7 @@ endif
+ gpl2lgpl := error.c error.h
+ tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
+-       tst-error1 tst-insremque
++       tst-error1 tst-insremque tst-mntent2
+ ifeq (no,$(cross-compiling))
+ tests: $(objpfx)tst-error1-mem
+ endif
+--- libc/misc/mntent_r.c       17 Dec 2003 23:29:02 -0000      1.20
++++ libc/misc/mntent_r.c       9 Dec 2006 22:05:59 -0000       1.21
+@@ -278,14 +279,11 @@ __hasmntopt (const struct mntent *mnt, c
+   while ((p = strstr (rest, opt)) != NULL)
+     {
+-      if (p == rest
+-        || (p[-1] == ','
+-            && (p[optlen] == '\0' ||
+-                p[optlen] == '='  ||
+-                p[optlen] == ',')))
++      if ((p == rest || p[-1] == ',')
++        && (p[optlen] == '\0' || p[optlen] == '=' || p[optlen] == ','))
+       return p;
+-      rest = strchr (rest, ',');
++      rest = strchr (p, ',');
+       if (rest == NULL)
+       break;
+       ++rest;
+--- libc/misc/tst-mntent2.c    1 Jan 1970 00:00:00 -0000
++++ libc/misc/tst-mntent2.c    9 Dec 2006 22:06:27 -0000       1.1
+@@ -0,0 +1,41 @@
++#include <mntent.h>
++#include <stdio.h>
++#include <string.h>
++
++
++int
++main (void)
++{
++  int result = 0;
++  struct mntent mef;
++
++  mef.mnt_fsname = strdupa ("/dev/sdf6");
++  mef.mnt_dir = strdupa ("/some dir");
++  mef.mnt_type = strdupa ("ext3");
++  mef.mnt_opts = strdupa ("opt1,opt2,noopt=6,rw,norw,brw");
++  mef.mnt_freq = 1;
++  mef.mnt_passno = 2;
++
++#define TEST(opt, found) \
++  if (!!hasmntopt (&mef, (opt)) != (found))                           \
++    {                                                                 \
++      printf ("Option %s was %sfound\n", (opt), (found) ? "not " : "");       \
++      result = 1;                                                     \
++    }
++
++  TEST ("opt1", 1)
++  TEST ("opt2", 1)
++  TEST ("noopt", 1)
++  TEST ("rw", 1)
++  TEST ("norw", 1)
++  TEST ("brw", 1)
++  TEST ("opt", 0)
++  TEST ("oopt", 0)
++  TEST ("w", 0)
++  TEST ("r", 0)
++  TEST ("br", 0)
++  TEST ("nor", 0)
++  TEST ("or", 0)
++
++  return result;
++}
diff --git a/src/patches/glibc/glibc-rh219145.patch b/src/patches/glibc/glibc-rh219145.patch
new file mode 100644 (file)
index 0000000..decdd8c
--- /dev/null
@@ -0,0 +1,38 @@
+2006-12-19  Jakub Jelinek  <jakub@redhat.com>
+
+       * nss/getXXbyYY_r.c: Include atomic.h.
+       (INTERNAL (REENTRANT_NAME)): Write startp after start_fct,
+       add atomic_write_barrier () in between.
+
+--- libc/nss/getXXbyYY_r.c     16 Sep 2004 22:24:09 -0000      1.61
++++ libc/nss/getXXbyYY_r.c     19 Dec 2006 15:45:08 -0000      1.62
+@@ -18,6 +18,7 @@
+    02111-1307 USA.  */
+ #include <assert.h>
++#include <atomic.h>
+ #include <errno.h>
+ #include <stdbool.h>
+ #include "nsswitch.h"
+@@ -173,9 +174,6 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, L
+       startp = (service_user *) -1l;
+       else
+       {
+-        startp = nip;
+-        start_fct = fct.l;
+-
+ #ifdef NEED__RES
+         /* The resolver code will really be used so we have to
+            initialize it.  */
+@@ -190,6 +188,11 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, L
+         if (!_res_hconf.initialized)
+           _res_hconf_init ();
+ #endif /* need _res_hconf */
++
++        start_fct = fct.l;
++        /* Make sure start_fct is written before startp.  */
++        atomic_write_barrier ();
++        startp = nip;
+       }
+     }
+   else
diff --git a/src/patches/glibc/glibc-rh220621.patch b/src/patches/glibc/glibc-rh220621.patch
new file mode 100644 (file)
index 0000000..fe573c9
--- /dev/null
@@ -0,0 +1,26 @@
+2006-12-22  Gavin Romig-Koch  <gavin@redhat.com>
+
+       * nis/nss_compat/compat-grp.c (internal_getgrgid_r): Don't
+       blacklist the group till after we look it up.
+
+--- libc/nis/nss_compat/compat-grp.c   31 Jul 2006 23:33:04 -0000      1.32
++++ libc/nis/nss_compat/compat-grp.c   22 Dec 2006 20:26:11 -0000      1.33
+@@ -580,13 +580,17 @@ internal_getgrgid_r (gid_t gid, struct g
+       /* +group */
+       if (result->gr_name[0] == '+' && result->gr_name[1] != '\0')
+       {
++        /* Yes, no +1, see the memcpy call below.  */
++        size_t len = strlen (result->gr_name);
++        char buf[len];
+         enum nss_status status;
+         /* Store the group in the blacklist for the "+" at the end of
+            /etc/group */
+-        blacklist_store_name (&result->gr_name[1], ent);
++        memcpy (buf, &result->gr_name[1], len);
+         status = getgrnam_plusgroup (&result->gr_name[1], result, ent,
+                                      buffer, buflen, errnop);
++        blacklist_store_name (buf, ent);
+         if (status == NSS_STATUS_SUCCESS && result->gr_gid == gid)
+           break;
+         else
diff --git a/src/patches/glibc/glibc-rh225315.patch b/src/patches/glibc/glibc-rh225315.patch
new file mode 100644 (file)
index 0000000..cdce9b2
--- /dev/null
@@ -0,0 +1,1104 @@
+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.
+
+--- libc/nscd/nscd-client.h    14 Jan 2007 05:23:40 -0000      1.24
++++ libc/nscd/nscd-client.h    31 Jan 2007 09:14:21 -0000      1.25
+@@ -323,10 +323,10 @@ static inline int __nscd_drop_map_ref (s
+ /* 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.  */
+--- libc/nscd/nscd_getai.c     15 May 2006 20:31:29 -0000      1.12
++++ libc/nscd/nscd_getai.c     31 Jan 2007 09:14:21 -0000      1.13
+@@ -42,6 +42,7 @@ __nscd_getai (const char *key, struct ns
+ {
+   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 ns
+                              &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 ns
+       }
+       /* 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 ns
+         /* 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 ns
+     }
+   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 ns
+       }
+       /* 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 ns
+   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;
+--- libc/nscd/nscd_getgr_r.c   15 May 2006 20:39:34 -0000      1.42
++++ libc/nscd/nscd_getgr_r.c   31 Jan 2007 09:14:21 -0000      1.43
+@@ -88,6 +89,7 @@ nscd_getgr_r (const char *key, size_t ke
+             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 ke
+                                                      &__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 ke
+        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 ke
+       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 ke
+         /* 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 ke
+       /* 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 ke
+       }
+       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 ke
+         /* 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 ke
+   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;
+--- libc/nscd/nscd_gethst_r.c  13 Jan 2007 07:30:16 -0000      1.35
++++ libc/nscd/nscd_gethst_r.c  31 Jan 2007 09:14:21 -0000      1.36
+@@ -118,7 +118,6 @@ nscd_gethst_r (const char *key, size_t k
+                              &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;
+@@ -126,18 +125,27 @@ nscd_gethst_r (const char *key, size_t k
+   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
+@@ -147,51 +155,47 @@ nscd_gethst_r (const char *key, size_t k
+         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;;
++        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)
+     {
+       struct iovec vec[4];
+       char *cp = buffer;
+@@ -207,15 +211,15 @@ nscd_gethst_r (const char *key, size_t k
+        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;
+@@ -227,12 +231,12 @@ nscd_gethst_r (const char *key, size_t k
+       /* 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)
+       {
+@@ -244,7 +248,7 @@ nscd_gethst_r (const char *key, size_t k
+         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;
+@@ -254,47 +258,47 @@ nscd_gethst_r (const char *key, size_t k
+       if (h_name == NULL)
+       {
+         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;
+           }
+@@ -304,13 +308,13 @@ nscd_gethst_r (const char *key, size_t k
+       }
+       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];
+@@ -320,10 +324,25 @@ nscd_gethst_r (const char *key, size_t k
+       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)
+@@ -342,14 +361,18 @@ nscd_gethst_r (const char *key, size_t k
+                 (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;
+@@ -358,7 +381,7 @@ nscd_gethst_r (const char *key, size_t k
+   else
+     {
+       /* Store the error number.  */
+-      *h_errnop = hst_resp->error;
++      *h_errnop = hst_resp.error;
+       /* The `errno' to some value != ERANGE.  */
+       __set_errno (ENOENT);
+@@ -370,19 +393,21 @@ nscd_gethst_r (const char *key, size_t k
+   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;
+--- libc/nscd/nscd_getpw_r.c   22 Sep 2005 14:35:11 -0000      1.31
++++ libc/nscd/nscd_getpw_r.c   31 Jan 2007 09:14:21 -0000      1.32
+@@ -88,76 +89,81 @@ nscd_getpw_r (const char *key, size_t ke
+             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 ke
+         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 ke
+   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;
+--- libc/nscd/nscd_helper.c    2 Oct 2006 16:33:51 -0000       1.17
++++ libc/nscd/nscd_helper.c    31 Jan 2007 09:14:21 -0000      1.18
+@@ -21,6 +21,7 @@
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <stdbool.h>
++#include <string.h>
+ #include <unistd.h>
+ #include <sys/mman.h>
+ #include <sys/poll.h>
+@@ -361,7 +362,10 @@ __nscd_get_map_ref (request_type type, c
+ }
+-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)
+ {
+@@ -373,16 +377,32 @@ __nscd_cache_search (request_type type, 
+     {
+       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)
+--- libc/nscd/nscd_initgroups.c        29 Sep 2006 17:05:21 -0000      1.11
++++ libc/nscd/nscd_initgroups.c        31 Jan 2007 09:14:21 -0000      1.12
+@@ -39,6 +39,7 @@ __nscd_getgrouplist (const char *user, g
+ {
+   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, g
+   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, g
+        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, g
+   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/src/patches/glibc/glibc-rh227016.patch b/src/patches/glibc/glibc-rh227016.patch
new file mode 100644 (file)
index 0000000..7a57513
--- /dev/null
@@ -0,0 +1,192 @@
+2006-08-24  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/generic/ldsodefs.h (DL_ADDR_SYM_MATCH): For undefined
+       symbol require exact match (these are PLTs).
+       * sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h
+       (_dl_ppc64_addr_sym_match): Likewise.
+
+       [BZ #2683]
+       * elf/dl-addr.c (_dl_addr): Don't ignore all undefined symbols.
+       If symbol has a value use it.
+       * elf/tst-dladdr1.c: New file.
+       * elf/Makefile: Add rules to build and run tst-addr1.
+
+2006-05-24  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2683]
+       * elf/dl-addr.c (_dl_addr): Don't match undefined references.
+
+2005-08-30  Jakub Jelinek  <jakub@redhat.com>
+           Alan Modra  <amodra@bigpond.net.au>
+
+       * elf/dl-addr.c (_dl_addr): Use DL_ADDR_SYM_MATCH macro.
+       * sysdeps/generic/ldsodefs.h (DL_ADDR_SYM_MATCH): Define.
+       * sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h: New file.
+
+--- libc/elf/dl-addr.c.jj      2004-10-19 12:44:19.000000000 -0400
++++ libc/elf/dl-addr.c 2007-02-13 02:56:54.000000000 -0500
+@@ -87,21 +87,16 @@ _dl_addr (const void *address, Dl_info *
+          the string table which generally follows the symbol table.  */
+       symtabend = (const ElfW(Sym) *) strtab;
+-      /* We assume that the string table follows the symbol table,
+-       because there is no way in ELF to know the size of the
+-       dynamic symbol table!!  */
+       for (matchsym = NULL; (void *) symtab < (void *) symtabend; ++symtab)
+-      if (addr >= match->l_addr + symtab->st_value
++      if ((ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
++           || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
+ #if defined USE_TLS
+           && ELFW(ST_TYPE) (symtab->st_info) != STT_TLS
+ #endif
+-          && ((symtab->st_size == 0
+-               && addr == match->l_addr + symtab->st_value)
+-              || addr < match->l_addr + symtab->st_value + symtab->st_size)
+-          && symtab->st_name < strtabsize
+-          && (matchsym == NULL || matchsym->st_value < symtab->st_value)
+-          && (ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
+-              || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK))
++          && (symtab->st_shndx != SHN_UNDEF
++              || symtab->st_value != 0)
++          && DL_ADDR_SYM_MATCH (match, symtab, matchsym, addr)
++          && symtab->st_name < strtabsize)
+         matchsym = (ElfW(Sym) *) symtab;
+       if (mapp)
+--- libc/sysdeps/generic/ldsodefs.h.jj 2005-04-05 22:50:21.000000000 -0400
++++ libc/sysdeps/generic/ldsodefs.h    2007-02-13 02:54:33.000000000 -0500
+@@ -81,6 +81,14 @@ typedef ElfW(Addr) lookup_t;
+ # define DL_DT_FINI_ADDRESS(map, start) (start)
+ #endif
++/* On some architectures dladdr can't use st_size of all symbols this way.  */
++#define DL_ADDR_SYM_MATCH(L, SYM, MATCHSYM, ADDR) \
++  ((ADDR) >= (L)->l_addr + (SYM)->st_value                            \
++   && ((((SYM)->st_shndx == SHN_UNDEF || (SYM)->st_size == 0)         \
++      && (ADDR) == (L)->l_addr + (SYM)->st_value)                     \
++       || (ADDR) < (L)->l_addr + (SYM)->st_value + (SYM)->st_size)    \
++   && ((MATCHSYM) == NULL || (MATCHSYM)->st_value < (SYM)->st_value))
++
+ /* Unmap a loaded object, called by _dl_close (). */
+ #ifndef DL_UNMAP_IS_SPECIAL
+ # define DL_UNMAP(map) \
+--- libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h.jj       2007-02-13 02:49:09.000000000 -0500
++++ libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h  2007-02-13 02:54:33.000000000 -0500
+@@ -0,0 +1,77 @@
++/* Run-time dynamic linker data structures for loaded ELF shared objects.
++   Copyright (C) 2005 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.  */
++
++#ifndef       _LDSODEFS_H
++
++/* Get the real definitions.  */
++#include_next <ldsodefs.h>
++
++/* Now define our stuff.  */
++
++static inline __attribute__ ((always_inline)) bool
++_dl_ppc64_is_opd_sym (const struct link_map *l, const ElfW(Sym) *sym)
++{
++  return (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC
++        && l->l_addr + sym->st_value >= (ElfW(Addr)) l->l_ld
++        && l->l_addr + sym->st_value < l->l_map_end
++        && sym->st_size != 0);
++}
++
++static inline __attribute__ ((always_inline)) bool
++_dl_ppc64_addr_sym_match (const struct link_map *l, const ElfW(Sym) *sym,
++                        const ElfW(Sym) *matchsym, ElfW(Addr) addr)
++{
++  ElfW(Addr) value = l->l_addr + sym->st_value;
++  if (_dl_ppc64_is_opd_sym (l, sym))
++    {
++      if (addr < value || addr >= value + 24)
++      {
++        value = *(ElfW(Addr) *) value;
++        if (addr < value || addr >= value + sym->st_size)
++          return false;
++      }
++    }
++  else if (sym->st_shndx == SHN_UNDEF || sym->st_size == 0)
++    {
++      if (addr != value)
++      return false;
++    }
++  else if (addr < value || addr >= value + sym->st_size)
++    return false;
++
++  if (matchsym == NULL)
++    return true;
++
++  ElfW(Addr) matchvalue = l->l_addr + matchsym->st_value;
++  if (_dl_ppc64_is_opd_sym (l, matchsym)
++      && (addr < matchvalue || addr > matchvalue + 24))
++    matchvalue = *(ElfW(Addr) *) matchvalue;
++
++  return matchvalue < value;
++}
++
++/* If this is a function symbol defined past the end of our dynamic
++   section, then it must be a function descriptor.  Allow these symbols
++   to match their associated function code range as well as the
++   descriptor addresses.  */
++#undef DL_ADDR_SYM_MATCH
++#define DL_ADDR_SYM_MATCH(L, SYM, MATCHSYM, ADDR) \
++  _dl_ppc64_addr_sym_match (L, SYM, MATCHSYM, ADDR)
++
++#endif /* ldsodefs.h */
+--- libc/elf/tst-addr1.c.jj    2007-02-13 02:59:02.000000000 -0500
++++ libc/elf/tst-addr1.c       2007-02-13 02:54:34.000000000 -0500
+@@ -0,0 +1,19 @@
++#include <dlfcn.h>
++#include <stdio.h>
++#include <string.h>
++
++static int
++do_test (void)
++{
++  Dl_info i;
++  if (dladdr (&printf, &i) == 0)
++    {
++      puts ("not found");
++      return 1;
++    }
++  printf ("found symbol %s in %s\n", i.dli_sname, i.dli_fname);
++  return i.dli_sname == NULL || strcmp (i.dli_sname, "printf") != 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/elf/Makefile.jj       2007-02-13 03:00:22.000000000 -0500
++++ libc/elf/Makefile  2007-02-13 02:55:35.000000000 -0500
+@@ -161,7 +161,8 @@ tests += loadtest restest1 preloadtest l
+        tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-align \
+        tst-align2 $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \
+        tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
+-       unload3 unload4 unload5 unload6 unload7 tst-global1 order2
++       unload3 unload4 unload5 unload6 unload7 tst-global1 order2 \
++       tst-addr1
+ #      reldep9
+ test-srcs = tst-pathopt
+ tests-vis-yes = vismain
+@@ -844,3 +845,5 @@ $(objpfx)tst-leaks1-mem: $(objpfx)tst-le
+       $(common-objpfx)malloc/mtrace $(objpfx)tst-leaks1.mtrace > $@
+ tst-leaks1-ENV = MALLOC_TRACE=$(objpfx)tst-leaks1.mtrace
++
++$(objpfx)tst-addr1: $(libdl)
diff --git a/src/patches/glibc/glibc-rh228103.patch b/src/patches/glibc/glibc-rh228103.patch
new file mode 100644 (file)
index 0000000..487064b
--- /dev/null
@@ -0,0 +1,17 @@
+2007-02-09  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
+       (__lll_mutex_timedlock_wait): Use correct pointer when we don't
+       call into the kernel to delay.
+
+--- libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S    17 Jan 2007 09:33:20 -0000      1.16
++++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S    10 Feb 2007 00:04:24 -0000      1.17
+@@ -164,7 +164,7 @@ __lll_mutex_timedlock_wait:
+ 8:                            /* NB: %edx == 2 */
+       xorl    %eax, %eax
+       LOCK
+-      cmpxchgl %edx, (%rdi)
++      cmpxchgl %edx, (%r12)
+       jnz     7f
+ 6:    addq    $16, %rsp
diff --git a/src/patches/glibc/glibc-rh228697.patch b/src/patches/glibc/glibc-rh228697.patch
new file mode 100644 (file)
index 0000000..4d3ff93
--- /dev/null
@@ -0,0 +1,1934 @@
+2007-11-10  Ulrich Drepper  <drepper@redhat.com>
+
+       * crypt/sha256-crypt.c: Fix a comment.
+       * crypt/sha512-crypt.c: Likewise.
+
+2007-10-28  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #5204]
+       * crypt/sha256c-test.c: Define TIMEOUT to 6 for ancient hardware.
+       * crypt/sha512c-test.c: Likewise.
+
+2007-09-19  Ulrich Drepper  <drepper@redhat.com>
+
+       * crypt/Makefile (libcrypt-routines): Add sha256-crypt, sha256,
+       sha512-crypt, and sha512.
+       (tests): Add sha256test, sha256c-test, sha512test, and sha512c-test.
+       (distribute): Add sha256.h and sha512.h.
+       * crypt/crypt-entry.c (crypt): Recognize the new $5$ and $6$ prefixes
+       and call the appropriate code.
+       * crypt/sha256-crypt.c: New file.
+       * crypt/sha256.c: New file.
+       * crypt/sha256.h: New file.
+       * crypt/sha256c-test.c: New file.
+       * crypt/sha256test.c: New file.
+       * crypt/sha512-crypt.c: New file.
+       * crypt/sha512.c: New file.
+       * crypt/sha512.h: New file.
+       * crypt/sha512c-test.c: New file.
+       * crypt/sha512test.c: New file.
+
+--- libc/crypt/Makefile        5 Oct 2005 19:33:35 -0000       1.10
++++ libc/crypt/Makefile        19 Sep 2007 20:37:33 -0000      1.11
+@@ -28,12 +28,13 @@ distribute := md5.h
+ extra-libs := libcrypt
+ extra-libs-others := $(extra-libs)
+-libcrypt-routines := crypt-entry md5-crypt md5 crypt crypt_util
++libcrypt-routines := crypt-entry md5-crypt md5 sha256-crypt sha256 \
++                   sha512-crypt sha512 crypt crypt_util
+-tests = cert md5test md5c-test
++tests = cert md5test md5c-test sha256test sha256c-test sha512test sha512c-test
+ distribute = ufc-crypt.h crypt-private.h ufc.c speeds.c README.ufc-crypt \
+-           Banner md5.h
++           Banner md5.h sha256.h sha512.h
+ include ../Makeconfig
+@@ -42,6 +43,8 @@ routines += $(libcrypt-routines)
+ endif
+ $(objpfx)md5test: $(objpfx)md5.o
++$(objpfx)sha256test: $(objpfx)sha256.o
++$(objpfx)sha512test: $(objpfx)sha512.o
+ include ../Rules
+--- libc/crypt/crypt-entry.c   6 Jul 2001 05:18:49 -0000       1.2
++++ libc/crypt/crypt-entry.c   19 Sep 2007 20:37:15 -0000      1.3
+@@ -55,6 +55,12 @@ void _ufc_clearmem (char *start, int cnt
+ extern char *__md5_crypt_r (const char *key, const char *salt, char *buffer,
+                           int buflen);
+ extern char *__md5_crypt (const char *key, const char *salt);
++extern char *__sha256_crypt_r (const char *key, const char *salt,
++                             char *buffer, int buflen);
++extern char *__sha256_crypt (const char *key, const char *salt);
++extern char *__sha512_crypt_r (const char *key, const char *salt,
++                             char *buffer, int buflen);
++extern char *__sha512_crypt (const char *key, const char *salt);
+ #endif
+ /* Define our magic string to mark salt for MD5 encryption
+@@ -62,6 +68,12 @@ extern char *__md5_crypt (const char *ke
+    encryption implementations.  */
+ static const char md5_salt_prefix[] = "$1$";
++/* Magic string for SHA256 encryption.  */
++static const char sha256_salt_prefix[] = "$5$";
++
++/* Magic string for SHA512 encryption.  */
++static const char sha512_salt_prefix[] = "$6$";
++
+ /* For use by the old, non-reentrant routines (crypt/encrypt/setkey)  */
+ extern struct crypt_data _ufc_foobar;
+@@ -84,6 +96,16 @@ __crypt_r (key, salt, data)
+   if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
+     return __md5_crypt_r (key, salt, (char *) data,
+                         sizeof (struct crypt_data));
++
++  /* Try to find out whether we have to use SHA256 encryption replacement.  */
++  if (strncmp (sha256_salt_prefix, salt, sizeof (sha256_salt_prefix) - 1) == 0)
++    return __sha256_crypt_r (key, salt, (char *) data,
++                           sizeof (struct crypt_data));
++
++  /* Try to find out whether we have to use SHA512 encryption replacement.  */
++  if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
++    return __sha512_crypt_r (key, salt, (char *) data,
++                           sizeof (struct crypt_data));
+ #endif
+   /*
+@@ -126,6 +148,14 @@ crypt (key, salt)
+   /* Try to find out whether we have to use MD5 encryption replacement.  */
+   if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
+     return __md5_crypt (key, salt);
++
++  /* Try to find out whether we have to use SHA256 encryption replacement.  */
++  if (strncmp (sha256_salt_prefix, salt, sizeof (sha256_salt_prefix) - 1) == 0)
++    return __sha256_crypt (key, salt);
++
++  /* Try to find out whether we have to use SHA512 encryption replacement.  */
++  if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
++    return __sha512_crypt (key, salt);
+ #endif
+   return __crypt_r (key, salt, &_ufc_foobar);
+--- libc/crypt/sha256-crypt.c  1 Jan 1970 00:00:00 -0000
++++ libc/crypt/sha256-crypt.c  10 Nov 2007 19:36:00 -0000      1.2
+@@ -0,0 +1,344 @@
++/* One way encryption based on SHA256 sum.
++   Copyright (C) 2007 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Ulrich Drepper <drepper@redhat.com>, 2007.
++
++   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 <assert.h>
++#include <errno.h>
++#include <stdbool.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/param.h>
++
++#include "sha256.h"
++
++
++/* Define our magic string to mark salt for SHA256 "encryption"
++   replacement.  */
++static const char sha256_salt_prefix[] = "$5$";
++
++/* Prefix for optional rounds specification.  */
++static const char sha256_rounds_prefix[] = "rounds=";
++
++/* Maximum salt string length.  */
++#define SALT_LEN_MAX 16
++/* Default number of rounds if not explicitly specified.  */
++#define ROUNDS_DEFAULT 5000
++/* Minimum number of rounds.  */
++#define ROUNDS_MIN 1000
++/* Maximum number of rounds.  */
++#define ROUNDS_MAX 999999999
++
++/* Table with characters for base64 transformation.  */
++static const char b64t[64] =
++"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
++
++
++/* Prototypes for local functions.  */
++extern char *__sha256_crypt_r (const char *key, const char *salt,
++                             char *buffer, int buflen);
++extern char *__sha256_crypt (const char *key, const char *salt);
++
++
++char *
++__sha256_crypt_r (key, salt, buffer, buflen)
++     const char *key;
++     const char *salt;
++     char *buffer;
++     int buflen;
++{
++  unsigned char alt_result[32]
++    __attribute__ ((__aligned__ (__alignof__ (uint32_t))));
++  unsigned char temp_result[32]
++    __attribute__ ((__aligned__ (__alignof__ (uint32_t))));
++  struct sha256_ctx ctx;
++  struct sha256_ctx alt_ctx;
++  size_t salt_len;
++  size_t key_len;
++  size_t cnt;
++  char *cp;
++  char *copied_key = NULL;
++  char *copied_salt = NULL;
++  char *p_bytes;
++  char *s_bytes;
++  /* Default number of rounds.  */
++  size_t rounds = ROUNDS_DEFAULT;
++  bool rounds_custom = false;
++
++  /* Find beginning of salt string.  The prefix should normally always
++     be present.  Just in case it is not.  */
++  if (strncmp (sha256_salt_prefix, salt, sizeof (sha256_salt_prefix) - 1) == 0)
++    /* Skip salt prefix.  */
++    salt += sizeof (sha256_salt_prefix) - 1;
++
++  if (strncmp (salt, sha256_rounds_prefix, sizeof (sha256_rounds_prefix) - 1)
++      == 0)
++    {
++      const char *num = salt + sizeof (sha256_rounds_prefix) - 1;
++      char *endp;
++      unsigned long int srounds = strtoul (num, &endp, 10);
++      if (*endp == '$')
++      {
++        salt = endp + 1;
++        rounds = MAX (ROUNDS_MIN, MIN (srounds, ROUNDS_MAX));
++        rounds_custom = true;
++      }
++    }
++
++  salt_len = MIN (strcspn (salt, "$"), SALT_LEN_MAX);
++  key_len = strlen (key);
++
++  if ((key - (char *) 0) % __alignof__ (uint32_t) != 0)
++    {
++      char *tmp = (char *) alloca (key_len + __alignof__ (uint32_t));
++      key = copied_key =
++      memcpy (tmp + __alignof__ (uint32_t)
++              - (tmp - (char *) 0) % __alignof__ (uint32_t),
++              key, key_len);
++      assert ((key - (char *) 0) % __alignof__ (uint32_t) == 0);
++    }
++
++  if ((salt - (char *) 0) % __alignof__ (uint32_t) != 0)
++    {
++      char *tmp = (char *) alloca (salt_len + __alignof__ (uint32_t));
++      salt = copied_salt =
++      memcpy (tmp + __alignof__ (uint32_t)
++              - (tmp - (char *) 0) % __alignof__ (uint32_t),
++              salt, salt_len);
++      assert ((salt - (char *) 0) % __alignof__ (uint32_t) == 0);
++    }
++
++  /* Prepare for the real work.  */
++  __sha256_init_ctx (&ctx);
++
++  /* Add the key string.  */
++  __sha256_process_bytes (key, key_len, &ctx);
++
++  /* The last part is the salt string.  This must be at most 16
++     characters and it ends at the first `$' character.  */
++  __sha256_process_bytes (salt, salt_len, &ctx);
++
++
++  /* Compute alternate SHA256 sum with input KEY, SALT, and KEY.  The
++     final result will be added to the first context.  */
++  __sha256_init_ctx (&alt_ctx);
++
++  /* Add key.  */
++  __sha256_process_bytes (key, key_len, &alt_ctx);
++
++  /* Add salt.  */
++  __sha256_process_bytes (salt, salt_len, &alt_ctx);
++
++  /* Add key again.  */
++  __sha256_process_bytes (key, key_len, &alt_ctx);
++
++  /* Now get result of this (32 bytes) and add it to the other
++     context.  */
++  __sha256_finish_ctx (&alt_ctx, alt_result);
++
++  /* Add for any character in the key one byte of the alternate sum.  */
++  for (cnt = key_len; cnt > 32; cnt -= 32)
++    __sha256_process_bytes (alt_result, 32, &ctx);
++  __sha256_process_bytes (alt_result, cnt, &ctx);
++
++  /* Take the binary representation of the length of the key and for every
++     1 add the alternate sum, for every 0 the key.  */
++  for (cnt = key_len; cnt > 0; cnt >>= 1)
++    if ((cnt & 1) != 0)
++      __sha256_process_bytes (alt_result, 32, &ctx);
++    else
++      __sha256_process_bytes (key, key_len, &ctx);
++
++  /* Create intermediate result.  */
++  __sha256_finish_ctx (&ctx, alt_result);
++
++  /* Start computation of P byte sequence.  */
++  __sha256_init_ctx (&alt_ctx);
++
++  /* For every character in the password add the entire password.  */
++  for (cnt = 0; cnt < key_len; ++cnt)
++    __sha256_process_bytes (key, key_len, &alt_ctx);
++
++  /* Finish the digest.  */
++  __sha256_finish_ctx (&alt_ctx, temp_result);
++
++  /* Create byte sequence P.  */
++  cp = p_bytes = alloca (key_len);
++  for (cnt = key_len; cnt >= 32; cnt -= 32)
++    cp = mempcpy (cp, temp_result, 32);
++  memcpy (cp, temp_result, cnt);
++
++  /* Start computation of S byte sequence.  */
++  __sha256_init_ctx (&alt_ctx);
++
++  /* For every character in the password add the entire password.  */
++  for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
++    __sha256_process_bytes (salt, salt_len, &alt_ctx);
++
++  /* Finish the digest.  */
++  __sha256_finish_ctx (&alt_ctx, temp_result);
++
++  /* Create byte sequence S.  */
++  cp = s_bytes = alloca (salt_len);
++  for (cnt = salt_len; cnt >= 32; cnt -= 32)
++    cp = mempcpy (cp, temp_result, 32);
++  memcpy (cp, temp_result, cnt);
++
++  /* Repeatedly run the collected hash value through SHA256 to burn
++     CPU cycles.  */
++  for (cnt = 0; cnt < rounds; ++cnt)
++    {
++      /* New context.  */
++      __sha256_init_ctx (&ctx);
++
++      /* Add key or last result.  */
++      if ((cnt & 1) != 0)
++      __sha256_process_bytes (p_bytes, key_len, &ctx);
++      else
++      __sha256_process_bytes (alt_result, 32, &ctx);
++
++      /* Add salt for numbers not divisible by 3.  */
++      if (cnt % 3 != 0)
++      __sha256_process_bytes (s_bytes, salt_len, &ctx);
++
++      /* Add key for numbers not divisible by 7.  */
++      if (cnt % 7 != 0)
++      __sha256_process_bytes (p_bytes, key_len, &ctx);
++
++      /* Add key or last result.  */
++      if ((cnt & 1) != 0)
++      __sha256_process_bytes (alt_result, 32, &ctx);
++      else
++      __sha256_process_bytes (p_bytes, key_len, &ctx);
++
++      /* Create intermediate result.  */
++      __sha256_finish_ctx (&ctx, alt_result);
++    }
++
++  /* Now we can construct the result string.  It consists of three
++     parts.  */
++  cp = __stpncpy (buffer, sha256_salt_prefix, MAX (0, buflen));
++  buflen -= sizeof (sha256_salt_prefix) - 1;
++
++  if (rounds_custom)
++    {
++      int n = snprintf (cp, MAX (0, buflen), "%s%zu$",
++                      sha256_rounds_prefix, rounds);
++      cp += n;
++      buflen -= n;
++    }
++
++  cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
++  buflen -= MIN ((size_t) MAX (0, buflen), salt_len);
++
++  if (buflen > 0)
++    {
++      *cp++ = '$';
++      --buflen;
++    }
++
++#define b64_from_24bit(B2, B1, B0, N)                                       \
++  do {                                                                              \
++    unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0);                             \
++    int n = (N);                                                            \
++    while (n-- > 0 && buflen > 0)                                           \
++      {                                                                             \
++      *cp++ = b64t[w & 0x3f];                                               \
++      --buflen;                                                             \
++      w >>= 6;                                                              \
++      }                                                                             \
++  } while (0)
++
++  b64_from_24bit (alt_result[0], alt_result[10], alt_result[20], 4);
++  b64_from_24bit (alt_result[21], alt_result[1], alt_result[11], 4);
++  b64_from_24bit (alt_result[12], alt_result[22], alt_result[2], 4);
++  b64_from_24bit (alt_result[3], alt_result[13], alt_result[23], 4);
++  b64_from_24bit (alt_result[24], alt_result[4], alt_result[14], 4);
++  b64_from_24bit (alt_result[15], alt_result[25], alt_result[5], 4);
++  b64_from_24bit (alt_result[6], alt_result[16], alt_result[26], 4);
++  b64_from_24bit (alt_result[27], alt_result[7], alt_result[17], 4);
++  b64_from_24bit (alt_result[18], alt_result[28], alt_result[8], 4);
++  b64_from_24bit (alt_result[9], alt_result[19], alt_result[29], 4);
++  b64_from_24bit (0, alt_result[31], alt_result[30], 3);
++  if (buflen <= 0)
++    {
++      __set_errno (ERANGE);
++      buffer = NULL;
++    }
++  else
++    *cp = '\0';               /* Terminate the string.  */
++
++  /* Clear the buffer for the intermediate result so that people
++     attaching to processes or reading core dumps cannot get any
++     information.  We do it in this way to clear correct_words[]
++     inside the SHA256 implementation as well.  */
++  __sha256_init_ctx (&ctx);
++  __sha256_finish_ctx (&ctx, alt_result);
++  memset (temp_result, '\0', sizeof (temp_result));
++  memset (p_bytes, '\0', key_len);
++  memset (s_bytes, '\0', salt_len);
++  memset (&ctx, '\0', sizeof (ctx));
++  memset (&alt_ctx, '\0', sizeof (alt_ctx));
++  if (copied_key != NULL)
++    memset (copied_key, '\0', key_len);
++  if (copied_salt != NULL)
++    memset (copied_salt, '\0', salt_len);
++
++  return buffer;
++}
++
++#ifndef _LIBC
++# define libc_freeres_ptr(decl) decl
++#endif
++libc_freeres_ptr (static char *buffer);
++
++/* This entry point is equivalent to the `crypt' function in Unix
++   libcs.  */
++char *
++__sha256_crypt (const char *key, const char *salt)
++{
++  /* We don't want to have an arbitrary limit in the size of the
++     password.  We can compute an upper bound for the size of the
++     result in advance and so we can prepare the buffer we pass to
++     `sha256_crypt_r'.  */
++  static int buflen;
++  int needed = (sizeof (sha256_salt_prefix) - 1
++              + sizeof (sha256_rounds_prefix) + 9 + 1
++              + strlen (salt) + 1 + 43 + 1);
++
++  if (buflen < needed)
++    {
++      char *new_buffer = (char *) realloc (buffer, needed);
++      if (new_buffer == NULL)
++      return NULL;
++
++      buffer = new_buffer;
++      buflen = needed;
++    }
++
++  return __sha256_crypt_r (key, salt, buffer, buflen);
++}
++
++#ifndef _LIBC
++static void
++__attribute__ ((__destructor__))
++free_mem (void)
++{
++  free (buffer);
++}
++#endif
+--- libc/crypt/sha256.c        1 Jan 1970 00:00:00 -0000
++++ libc/crypt/sha256.c        19 Sep 2007 20:35:44 -0000      1.1
+@@ -0,0 +1,304 @@
++/* Functions to compute SHA256 message digest of files or memory blocks.
++   according to the definition of SHA256 in FIPS 180-2.
++   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.  */
++
++/* Written by Ulrich Drepper <drepper@redhat.com>, 2007.  */
++
++#ifdef HAVE_CONFIG_H
++# include <config.h>
++#endif
++
++#include <endian.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include "sha256.h"
++
++#if __BYTE_ORDER == __LITTLE_ENDIAN
++# ifdef _LIBC
++#  include <byteswap.h>
++#  define SWAP(n) bswap_32 (n)
++# else
++#  define SWAP(n) \
++    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
++# endif
++#else
++# define SWAP(n) (n)
++#endif
++
++
++/* This array contains the bytes used to pad the buffer to the next
++   64-byte boundary.  (FIPS 180-2:5.1.1)  */
++static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
++
++
++/* Constants for SHA256 from FIPS 180-2:4.2.2.  */
++static const uint32_t K[64] =
++  {
++    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
++    0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
++    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
++    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
++    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
++    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
++    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
++    0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
++    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
++    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
++    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
++    0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
++    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
++    0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
++    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
++    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
++  };
++
++
++/* Process LEN bytes of BUFFER, accumulating context into CTX.
++   It is assumed that LEN % 64 == 0.  */
++static void
++sha256_process_block (const void *buffer, size_t len, struct sha256_ctx *ctx)
++{
++  const uint32_t *words = buffer;
++  size_t nwords = len / sizeof (uint32_t);
++  uint32_t a = ctx->H[0];
++  uint32_t b = ctx->H[1];
++  uint32_t c = ctx->H[2];
++  uint32_t d = ctx->H[3];
++  uint32_t e = ctx->H[4];
++  uint32_t f = ctx->H[5];
++  uint32_t g = ctx->H[6];
++  uint32_t h = ctx->H[7];
++
++  /* First increment the byte count.  FIPS 180-2 specifies the possible
++     length of the file up to 2^64 bits.  Here we only compute the
++     number of bytes.  Do a double word increment.  */
++  ctx->total[0] += len;
++  if (ctx->total[0] < len)
++    ++ctx->total[1];
++
++  /* Process all bytes in the buffer with 64 bytes in each round of
++     the loop.  */
++  while (nwords > 0)
++    {
++      uint32_t W[64];
++      uint32_t a_save = a;
++      uint32_t b_save = b;
++      uint32_t c_save = c;
++      uint32_t d_save = d;
++      uint32_t e_save = e;
++      uint32_t f_save = f;
++      uint32_t g_save = g;
++      uint32_t h_save = h;
++
++      /* Operators defined in FIPS 180-2:4.1.2.  */
++#define Ch(x, y, z) ((x & y) ^ (~x & z))
++#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
++#define S0(x) (CYCLIC (x, 2) ^ CYCLIC (x, 13) ^ CYCLIC (x, 22))
++#define S1(x) (CYCLIC (x, 6) ^ CYCLIC (x, 11) ^ CYCLIC (x, 25))
++#define R0(x) (CYCLIC (x, 7) ^ CYCLIC (x, 18) ^ (x >> 3))
++#define R1(x) (CYCLIC (x, 17) ^ CYCLIC (x, 19) ^ (x >> 10))
++
++      /* It is unfortunate that C does not provide an operator for
++       cyclic rotation.  Hope the C compiler is smart enough.  */
++#define CYCLIC(w, s) ((w >> s) | (w << (32 - s)))
++
++      /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2.  */
++      for (unsigned int t = 0; t < 16; ++t)
++      {
++        W[t] = SWAP (*words);
++        ++words;
++      }
++      for (unsigned int t = 16; t < 64; ++t)
++      W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16];
++
++      /* The actual computation according to FIPS 180-2:6.2.2 step 3.  */
++      for (unsigned int t = 0; t < 64; ++t)
++      {
++        uint32_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
++        uint32_t T2 = S0 (a) + Maj (a, b, c);
++        h = g;
++        g = f;
++        f = e;
++        e = d + T1;
++        d = c;
++        c = b;
++        b = a;
++        a = T1 + T2;
++      }
++
++      /* Add the starting values of the context according to FIPS 180-2:6.2.2
++       step 4.  */
++      a += a_save;
++      b += b_save;
++      c += c_save;
++      d += d_save;
++      e += e_save;
++      f += f_save;
++      g += g_save;
++      h += h_save;
++
++      /* Prepare for the next round.  */
++      nwords -= 16;
++    }
++
++  /* Put checksum in context given as argument.  */
++  ctx->H[0] = a;
++  ctx->H[1] = b;
++  ctx->H[2] = c;
++  ctx->H[3] = d;
++  ctx->H[4] = e;
++  ctx->H[5] = f;
++  ctx->H[6] = g;
++  ctx->H[7] = h;
++}
++
++
++/* Initialize structure containing state of computation.
++   (FIPS 180-2:5.3.2)  */
++void
++__sha256_init_ctx (ctx)
++     struct sha256_ctx *ctx;
++{
++  ctx->H[0] = 0x6a09e667;
++  ctx->H[1] = 0xbb67ae85;
++  ctx->H[2] = 0x3c6ef372;
++  ctx->H[3] = 0xa54ff53a;
++  ctx->H[4] = 0x510e527f;
++  ctx->H[5] = 0x9b05688c;
++  ctx->H[6] = 0x1f83d9ab;
++  ctx->H[7] = 0x5be0cd19;
++
++  ctx->total[0] = ctx->total[1] = 0;
++  ctx->buflen = 0;
++}
++
++
++/* Process the remaining bytes in the internal buffer and the usual
++   prolog according to the standard and write the result to RESBUF.
++
++   IMPORTANT: On some systems it is required that RESBUF is correctly
++   aligned for a 32 bits value.  */
++void *
++__sha256_finish_ctx (ctx, resbuf)
++     struct sha256_ctx *ctx;
++     void *resbuf;
++{
++  /* Take yet unprocessed bytes into account.  */
++  uint32_t bytes = ctx->buflen;
++  size_t pad;
++
++  /* Now count remaining bytes.  */
++  ctx->total[0] += bytes;
++  if (ctx->total[0] < bytes)
++    ++ctx->total[1];
++
++  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
++  memcpy (&ctx->buffer[bytes], fillbuf, pad);
++
++  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
++  *(uint32_t *) &ctx->buffer[bytes + pad + 4] = SWAP (ctx->total[0] << 3);
++  *(uint32_t *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) |
++                                                (ctx->total[0] >> 29));
++
++  /* Process last bytes.  */
++  sha256_process_block (ctx->buffer, bytes + pad + 8, ctx);
++
++  /* Put result from CTX in first 32 bytes following RESBUF.  */
++  for (unsigned int i = 0; i < 8; ++i)
++    ((uint32_t *) resbuf)[i] = SWAP (ctx->H[i]);
++
++  return resbuf;
++}
++
++
++void
++__sha256_process_bytes (buffer, len, ctx)
++     const void *buffer;
++     size_t len;
++     struct sha256_ctx *ctx;
++{
++  /* When we already have some bits in our internal buffer concatenate
++     both inputs first.  */
++  if (ctx->buflen != 0)
++    {
++      size_t left_over = ctx->buflen;
++      size_t add = 128 - left_over > len ? len : 128 - left_over;
++
++      memcpy (&ctx->buffer[left_over], buffer, add);
++      ctx->buflen += add;
++
++      if (ctx->buflen > 64)
++      {
++        sha256_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
++
++        ctx->buflen &= 63;
++        /* The regions in the following copy operation cannot overlap.  */
++        memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
++                ctx->buflen);
++      }
++
++      buffer = (const char *) buffer + add;
++      len -= add;
++    }
++
++  /* Process available complete blocks.  */
++  if (len >= 64)
++    {
++#if !_STRING_ARCH_unaligned
++/* To check alignment gcc has an appropriate operator.  Other
++   compilers don't.  */
++# if __GNUC__ >= 2
++#  define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint32_t) != 0)
++# else
++#  define UNALIGNED_P(p) (((uintptr_t) p) % sizeof (uint32_t) != 0)
++# endif
++      if (UNALIGNED_P (buffer))
++      while (len > 64)
++        {
++          sha256_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
++          buffer = (const char *) buffer + 64;
++          len -= 64;
++        }
++      else
++#endif
++      {
++        sha256_process_block (buffer, len & ~63, ctx);
++        buffer = (const char *) buffer + (len & ~63);
++        len &= 63;
++      }
++    }
++
++  /* Move remaining bytes into internal buffer.  */
++  if (len > 0)
++    {
++      size_t left_over = ctx->buflen;
++
++      memcpy (&ctx->buffer[left_over], buffer, len);
++      left_over += len;
++      if (left_over >= 64)
++      {
++        sha256_process_block (ctx->buffer, 64, ctx);
++        left_over -= 64;
++        memcpy (ctx->buffer, &ctx->buffer[64], left_over);
++      }
++      ctx->buflen = left_over;
++    }
++}
+--- libc/crypt/sha256.h        1 Jan 1970 00:00:00 -0000
++++ libc/crypt/sha256.h        19 Sep 2007 20:35:50 -0000      1.1
+@@ -0,0 +1,58 @@
++/* Declaration of functions and data types used for SHA256 sum computing
++   library functions.
++   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.  */
++
++#ifndef _SHA256_H
++#define _SHA256_H 1
++
++#include <limits.h>
++#include <stdint.h>
++#include <stdio.h>
++
++
++/* Structure to save state of computation between the single steps.  */
++struct sha256_ctx
++{
++  uint32_t H[8];
++
++  uint32_t total[2];
++  uint32_t buflen;
++  char buffer[128] __attribute__ ((__aligned__ (__alignof__ (uint32_t))));
++};
++
++/* Initialize structure containing state of computation.
++   (FIPS 180-2: 5.3.2)  */
++extern void __sha256_init_ctx (struct sha256_ctx *ctx) __THROW;
++
++/* Starting with the result of former calls of this function (or the
++   initialization function update the context for the next LEN bytes
++   starting at BUFFER.
++   It is NOT required that LEN is a multiple of 64.  */
++extern void __sha256_process_bytes (const void *buffer, size_t len,
++                                  struct sha256_ctx *ctx) __THROW;
++
++/* Process the remaining bytes in the buffer and put result from CTX
++   in first 32 bytes following RESBUF.
++
++   IMPORTANT: On some systems it is required that RESBUF is correctly
++   aligned for a 32 bits value.  */
++extern void *__sha256_finish_ctx (struct sha256_ctx *ctx, void *resbuf)
++  __THROW;
++
++#endif /* sha256.h */
+--- libc/crypt/sha256c-test.c  1 Jan 1970 00:00:00 -0000
++++ libc/crypt/sha256c-test.c  28 Oct 2007 19:46:43 -0000      1.2
+@@ -0,0 +1,62 @@
++#include <crypt.h>
++#include <stdio.h>
++#include <string.h>
++
++static const struct
++{
++  const char *salt;
++  const char *input;
++  const char *expected;
++} tests[] =
++{
++  { "$5$saltstring", "Hello world!",
++    "$5$saltstring$5B8vYYiY.CVt1RlTTf8KbXBH3hsxY/GNooZaBBGWEc5" },
++  { "$5$rounds=10000$saltstringsaltstring", "Hello world!",
++    "$5$rounds=10000$saltstringsaltst$3xv.VbSHBb41AL9AvLeujZkZRBAwqFMz2."
++    "opqey6IcA" },
++  { "$5$rounds=5000$toolongsaltstring", "This is just a test",
++    "$5$rounds=5000$toolongsaltstrin$Un/5jzAHMgOGZ5.mWJpuVolil07guHPvOW8"
++    "mGRcvxa5" },
++  { "$5$rounds=1400$anotherlongsaltstring",
++    "a very much longer text to encrypt.  This one even stretches over more"
++    "than one line.",
++    "$5$rounds=1400$anotherlongsalts$Rx.j8H.h8HjEDGomFU8bDkXm3XIUnzyxf12"
++    "oP84Bnq1" },
++  { "$5$rounds=77777$short",
++    "we have a short salt string but not a short password",
++    "$5$rounds=77777$short$JiO1O3ZpDAxGJeaDIuqCoEFysAe1mZNJRs3pw0KQRd/" },
++  { "$5$rounds=123456$asaltof16chars..", "a short string",
++    "$5$rounds=123456$asaltof16chars..$gP3VQ/6X7UUEW3HkBn2w1/Ptq2jxPyzV/"
++    "cZKmF/wJvD" },
++  { "$5$rounds=10$roundstoolow", "the minimum number is still observed",
++    "$5$rounds=1000$roundstoolow$yfvwcWrQ8l/K0DAWyuPMDNHpIVlTQebY9l/gL97"
++    "2bIC" },
++};
++#define ntests (sizeof (tests) / sizeof (tests[0]))
++
++
++
++static int
++do_test (void)
++{
++  int result = 0;
++  int i;
++
++  for (i = 0; i < ntests; ++i)
++    {
++      char *cp = crypt (tests[i].input, tests[i].salt);
++
++      if (strcmp (cp, tests[i].expected) != 0)
++      {
++        printf ("test %d: expected \"%s\", got \"%s\"\n",
++                i, tests[i].expected, cp);
++        result = 1;
++      }
++    }
++
++  return result;
++}
++
++#define TIMEOUT 6
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/crypt/sha256test.c    1 Jan 1970 00:00:00 -0000
++++ libc/crypt/sha256test.c    19 Sep 2007 20:36:15 -0000      1.1
+@@ -0,0 +1,92 @@
++#include <string.h>
++#include "sha256.h"
++
++static const struct
++{
++  const char *input;
++  const char result[32];
++} tests[] =
++  {
++    /* Test vectors from FIPS 180-2: appendix B.1.  */
++    { "abc",
++      "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23"
++      "\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad" },
++    /* Test vectors from FIPS 180-2: appendix B.2.  */
++    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
++      "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39"
++      "\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1" },
++    /* Test vectors from the NESSIE project.  */
++    { "",
++      "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24"
++      "\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55" },
++    { "a",
++      "\xca\x97\x81\x12\xca\x1b\xbd\xca\xfa\xc2\x31\xb3\x9a\x23\xdc\x4d"
++      "\xa7\x86\xef\xf8\x14\x7c\x4e\x72\xb9\x80\x77\x85\xaf\xee\x48\xbb" },
++    { "message digest",
++      "\xf7\x84\x6f\x55\xcf\x23\xe1\x4e\xeb\xea\xb5\xb4\xe1\x55\x0c\xad"
++      "\x5b\x50\x9e\x33\x48\xfb\xc4\xef\xa3\xa1\x41\x3d\x39\x3c\xb6\x50" },
++    { "abcdefghijklmnopqrstuvwxyz",
++      "\x71\xc4\x80\xdf\x93\xd6\xae\x2f\x1e\xfa\xd1\x44\x7c\x66\xc9\x52"
++      "\x5e\x31\x62\x18\xcf\x51\xfc\x8d\x9e\xd8\x32\xf2\xda\xf1\x8b\x73" },
++    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
++      "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39"
++      "\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1" },
++    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
++      "\xdb\x4b\xfc\xbd\x4d\xa0\xcd\x85\xa6\x0c\x3c\x37\xd3\xfb\xd8\x80"
++      "\x5c\x77\xf1\x5f\xc6\xb1\xfd\xfe\x61\x4e\xe0\xa7\xc8\xfd\xb4\xc0" },
++    { "123456789012345678901234567890123456789012345678901234567890"
++      "12345678901234567890",
++      "\xf3\x71\xbc\x4a\x31\x1f\x2b\x00\x9e\xef\x95\x2d\xd8\x3c\xa8\x0e"
++      "\x2b\x60\x02\x6c\x8e\x93\x55\x92\xd0\xf9\xc3\x08\x45\x3c\x81\x3e" }
++  };
++
++
++int
++main (void)
++{
++  struct sha256_ctx ctx;
++  char sum[32];
++  int result = 0;
++  int cnt;
++
++  for (cnt = 0; cnt < (int) (sizeof (tests) / sizeof (tests[0])); ++cnt)
++    {
++      __sha256_init_ctx (&ctx);
++      __sha256_process_bytes (tests[cnt].input, strlen (tests[cnt].input),
++                            &ctx);
++      __sha256_finish_ctx (&ctx, sum);
++      if (memcmp (tests[cnt].result, sum, 32) != 0)
++      {
++        printf ("test %d run %d failed\n", cnt, 1);
++        result = 1;
++      }
++
++      __sha256_init_ctx (&ctx);
++      for (int i = 0; tests[cnt].input[i] != '\0'; ++i)
++      __sha256_process_bytes (&tests[cnt].input[i], 1, &ctx);
++      __sha256_finish_ctx (&ctx, sum);
++      if (memcmp (tests[cnt].result, sum, 32) != 0)
++      {
++        printf ("test %d run %d failed\n", cnt, 2);
++        result = 1;
++      }
++    }
++
++  /* Test vector from FIPS 180-2: appendix B.3.  */
++  char buf[1000];
++  memset (buf, 'a', sizeof (buf));
++  __sha256_init_ctx (&ctx);
++  for (int i = 0; i < 1000; ++i)
++    __sha256_process_bytes (buf, sizeof (buf), &ctx);
++  __sha256_finish_ctx (&ctx, sum);
++  static const char expected[32] =
++    "\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67"
++    "\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0";
++  if (memcmp (expected, sum, 32) != 0)
++    {
++      printf ("test %d failed\n", cnt);
++      result = 1;
++    }
++
++  return result;
++}
+--- libc/crypt/sha512-crypt.c  1 Jan 1970 00:00:00 -0000
++++ libc/crypt/sha512-crypt.c  10 Nov 2007 19:36:00 -0000      1.2
+@@ -0,0 +1,356 @@
++/* One way encryption based on SHA512 sum.
++   Copyright (C) 2007 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Ulrich Drepper <drepper@redhat.com>, 2007.
++
++   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 <assert.h>
++#include <errno.h>
++#include <stdbool.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/param.h>
++
++#include "sha512.h"
++
++
++/* Define our magic string to mark salt for SHA512 "encryption"
++   replacement.  */
++static const char sha512_salt_prefix[] = "$6$";
++
++/* Prefix for optional rounds specification.  */
++static const char sha512_rounds_prefix[] = "rounds=";
++
++/* Maximum salt string length.  */
++#define SALT_LEN_MAX 16
++/* Default number of rounds if not explicitly specified.  */
++#define ROUNDS_DEFAULT 5000
++/* Minimum number of rounds.  */
++#define ROUNDS_MIN 1000
++/* Maximum number of rounds.  */
++#define ROUNDS_MAX 999999999
++
++/* Table with characters for base64 transformation.  */
++static const char b64t[64] =
++"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
++
++
++/* Prototypes for local functions.  */
++extern char *__sha512_crypt_r (const char *key, const char *salt,
++                             char *buffer, int buflen);
++extern char *__sha512_crypt (const char *key, const char *salt);
++
++
++char *
++__sha512_crypt_r (key, salt, buffer, buflen)
++     const char *key;
++     const char *salt;
++     char *buffer;
++     int buflen;
++{
++  unsigned char alt_result[64]
++    __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
++  unsigned char temp_result[64]
++    __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
++  struct sha512_ctx ctx;
++  struct sha512_ctx alt_ctx;
++  size_t salt_len;
++  size_t key_len;
++  size_t cnt;
++  char *cp;
++  char *copied_key = NULL;
++  char *copied_salt = NULL;
++  char *p_bytes;
++  char *s_bytes;
++  /* Default number of rounds.  */
++  size_t rounds = ROUNDS_DEFAULT;
++  bool rounds_custom = false;
++
++  /* Find beginning of salt string.  The prefix should normally always
++     be present.  Just in case it is not.  */
++  if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
++    /* Skip salt prefix.  */
++    salt += sizeof (sha512_salt_prefix) - 1;
++
++  if (strncmp (salt, sha512_rounds_prefix, sizeof (sha512_rounds_prefix) - 1)
++      == 0)
++    {
++      const char *num = salt + sizeof (sha512_rounds_prefix) - 1;
++      char *endp;
++      unsigned long int srounds = strtoul (num, &endp, 10);
++      if (*endp == '$')
++      {
++        salt = endp + 1;
++        rounds = MAX (ROUNDS_MIN, MIN (srounds, ROUNDS_MAX));
++        rounds_custom = true;
++      }
++    }
++
++  salt_len = MIN (strcspn (salt, "$"), SALT_LEN_MAX);
++  key_len = strlen (key);
++
++  if ((key - (char *) 0) % __alignof__ (uint64_t) != 0)
++    {
++      char *tmp = (char *) alloca (key_len + __alignof__ (uint64_t));
++      key = copied_key =
++      memcpy (tmp + __alignof__ (uint64_t)
++              - (tmp - (char *) 0) % __alignof__ (uint64_t),
++              key, key_len);
++      assert ((key - (char *) 0) % __alignof__ (uint64_t) == 0);
++    }
++
++  if ((salt - (char *) 0) % __alignof__ (uint64_t) != 0)
++    {
++      char *tmp = (char *) alloca (salt_len + __alignof__ (uint64_t));
++      salt = copied_salt =
++      memcpy (tmp + __alignof__ (uint64_t)
++              - (tmp - (char *) 0) % __alignof__ (uint64_t),
++              salt, salt_len);
++      assert ((salt - (char *) 0) % __alignof__ (uint64_t) == 0);
++    }
++
++  /* Prepare for the real work.  */
++  __sha512_init_ctx (&ctx);
++
++  /* Add the key string.  */
++  __sha512_process_bytes (key, key_len, &ctx);
++
++  /* The last part is the salt string.  This must be at most 16
++     characters and it ends at the first `$' character.  */
++  __sha512_process_bytes (salt, salt_len, &ctx);
++
++
++  /* Compute alternate SHA512 sum with input KEY, SALT, and KEY.  The
++     final result will be added to the first context.  */
++  __sha512_init_ctx (&alt_ctx);
++
++  /* Add key.  */
++  __sha512_process_bytes (key, key_len, &alt_ctx);
++
++  /* Add salt.  */
++  __sha512_process_bytes (salt, salt_len, &alt_ctx);
++
++  /* Add key again.  */
++  __sha512_process_bytes (key, key_len, &alt_ctx);
++
++  /* Now get result of this (64 bytes) and add it to the other
++     context.  */
++  __sha512_finish_ctx (&alt_ctx, alt_result);
++
++  /* Add for any character in the key one byte of the alternate sum.  */
++  for (cnt = key_len; cnt > 64; cnt -= 64)
++    __sha512_process_bytes (alt_result, 64, &ctx);
++  __sha512_process_bytes (alt_result, cnt, &ctx);
++
++  /* Take the binary representation of the length of the key and for every
++     1 add the alternate sum, for every 0 the key.  */
++  for (cnt = key_len; cnt > 0; cnt >>= 1)
++    if ((cnt & 1) != 0)
++      __sha512_process_bytes (alt_result, 64, &ctx);
++    else
++      __sha512_process_bytes (key, key_len, &ctx);
++
++  /* Create intermediate result.  */
++  __sha512_finish_ctx (&ctx, alt_result);
++
++  /* Start computation of P byte sequence.  */
++  __sha512_init_ctx (&alt_ctx);
++
++  /* For every character in the password add the entire password.  */
++  for (cnt = 0; cnt < key_len; ++cnt)
++    __sha512_process_bytes (key, key_len, &alt_ctx);
++
++  /* Finish the digest.  */
++  __sha512_finish_ctx (&alt_ctx, temp_result);
++
++  /* Create byte sequence P.  */
++  cp = p_bytes = alloca (key_len);
++  for (cnt = key_len; cnt >= 64; cnt -= 64)
++    cp = mempcpy (cp, temp_result, 64);
++  memcpy (cp, temp_result, cnt);
++
++  /* Start computation of S byte sequence.  */
++  __sha512_init_ctx (&alt_ctx);
++
++  /* For every character in the password add the entire password.  */
++  for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
++    __sha512_process_bytes (salt, salt_len, &alt_ctx);
++
++  /* Finish the digest.  */
++  __sha512_finish_ctx (&alt_ctx, temp_result);
++
++  /* Create byte sequence S.  */
++  cp = s_bytes = alloca (salt_len);
++  for (cnt = salt_len; cnt >= 64; cnt -= 64)
++    cp = mempcpy (cp, temp_result, 64);
++  memcpy (cp, temp_result, cnt);
++
++  /* Repeatedly run the collected hash value through SHA512 to burn
++     CPU cycles.  */
++  for (cnt = 0; cnt < rounds; ++cnt)
++    {
++      /* New context.  */
++      __sha512_init_ctx (&ctx);
++
++      /* Add key or last result.  */
++      if ((cnt & 1) != 0)
++      __sha512_process_bytes (p_bytes, key_len, &ctx);
++      else
++      __sha512_process_bytes (alt_result, 64, &ctx);
++
++      /* Add salt for numbers not divisible by 3.  */
++      if (cnt % 3 != 0)
++      __sha512_process_bytes (s_bytes, salt_len, &ctx);
++
++      /* Add key for numbers not divisible by 7.  */
++      if (cnt % 7 != 0)
++      __sha512_process_bytes (p_bytes, key_len, &ctx);
++
++      /* Add key or last result.  */
++      if ((cnt & 1) != 0)
++      __sha512_process_bytes (alt_result, 64, &ctx);
++      else
++      __sha512_process_bytes (p_bytes, key_len, &ctx);
++
++      /* Create intermediate result.  */
++      __sha512_finish_ctx (&ctx, alt_result);
++    }
++
++  /* Now we can construct the result string.  It consists of three
++     parts.  */
++  cp = __stpncpy (buffer, sha512_salt_prefix, MAX (0, buflen));
++  buflen -= sizeof (sha512_salt_prefix) - 1;
++
++  if (rounds_custom)
++    {
++      int n = snprintf (cp, MAX (0, buflen), "%s%zu$",
++                      sha512_rounds_prefix, rounds);
++      cp += n;
++      buflen -= n;
++    }
++
++  cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
++  buflen -= MIN ((size_t) MAX (0, buflen), salt_len);
++
++  if (buflen > 0)
++    {
++      *cp++ = '$';
++      --buflen;
++    }
++
++#define b64_from_24bit(B2, B1, B0, N)                                       \
++  do {                                                                              \
++    unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0);                             \
++    int n = (N);                                                            \
++    while (n-- > 0 && buflen > 0)                                           \
++      {                                                                             \
++      *cp++ = b64t[w & 0x3f];                                               \
++      --buflen;                                                             \
++      w >>= 6;                                                              \
++      }                                                                             \
++  } while (0)
++
++  b64_from_24bit (alt_result[0], alt_result[21], alt_result[42], 4);
++  b64_from_24bit (alt_result[22], alt_result[43], alt_result[1], 4);
++  b64_from_24bit (alt_result[44], alt_result[2], alt_result[23], 4);
++  b64_from_24bit (alt_result[3], alt_result[24], alt_result[45], 4);
++  b64_from_24bit (alt_result[25], alt_result[46], alt_result[4], 4);
++  b64_from_24bit (alt_result[47], alt_result[5], alt_result[26], 4);
++  b64_from_24bit (alt_result[6], alt_result[27], alt_result[48], 4);
++  b64_from_24bit (alt_result[28], alt_result[49], alt_result[7], 4);
++  b64_from_24bit (alt_result[50], alt_result[8], alt_result[29], 4);
++  b64_from_24bit (alt_result[9], alt_result[30], alt_result[51], 4);
++  b64_from_24bit (alt_result[31], alt_result[52], alt_result[10], 4);
++  b64_from_24bit (alt_result[53], alt_result[11], alt_result[32], 4);
++  b64_from_24bit (alt_result[12], alt_result[33], alt_result[54], 4);
++  b64_from_24bit (alt_result[34], alt_result[55], alt_result[13], 4);
++  b64_from_24bit (alt_result[56], alt_result[14], alt_result[35], 4);
++  b64_from_24bit (alt_result[15], alt_result[36], alt_result[57], 4);
++  b64_from_24bit (alt_result[37], alt_result[58], alt_result[16], 4);
++  b64_from_24bit (alt_result[59], alt_result[17], alt_result[38], 4);
++  b64_from_24bit (alt_result[18], alt_result[39], alt_result[60], 4);
++  b64_from_24bit (alt_result[40], alt_result[61], alt_result[19], 4);
++  b64_from_24bit (alt_result[62], alt_result[20], alt_result[41], 4);
++  b64_from_24bit (0, 0, alt_result[63], 2);
++
++  if (buflen <= 0)
++    {
++      __set_errno (ERANGE);
++      buffer = NULL;
++    }
++  else
++    *cp = '\0';               /* Terminate the string.  */
++
++  /* Clear the buffer for the intermediate result so that people
++     attaching to processes or reading core dumps cannot get any
++     information.  We do it in this way to clear correct_words[]
++     inside the SHA512 implementation as well.  */
++  __sha512_init_ctx (&ctx);
++  __sha512_finish_ctx (&ctx, alt_result);
++  memset (temp_result, '\0', sizeof (temp_result));
++  memset (p_bytes, '\0', key_len);
++  memset (s_bytes, '\0', salt_len);
++  memset (&ctx, '\0', sizeof (ctx));
++  memset (&alt_ctx, '\0', sizeof (alt_ctx));
++  if (copied_key != NULL)
++    memset (copied_key, '\0', key_len);
++  if (copied_salt != NULL)
++    memset (copied_salt, '\0', salt_len);
++
++  return buffer;
++}
++
++#ifndef _LIBC
++# define libc_freeres_ptr(decl) decl
++#endif
++libc_freeres_ptr (static char *buffer);
++
++/* This entry point is equivalent to the `crypt' function in Unix
++   libcs.  */
++char *
++__sha512_crypt (const char *key, const char *salt)
++{
++  /* We don't want to have an arbitrary limit in the size of the
++     password.  We can compute an upper bound for the size of the
++     result in advance and so we can prepare the buffer we pass to
++     `sha512_crypt_r'.  */
++  static int buflen;
++  int needed = (sizeof (sha512_salt_prefix) - 1
++              + sizeof (sha512_rounds_prefix) + 9 + 1
++              + strlen (salt) + 1 + 86 + 1);
++
++  if (buflen < needed)
++    {
++      char *new_buffer = (char *) realloc (buffer, needed);
++      if (new_buffer == NULL)
++      return NULL;
++
++      buffer = new_buffer;
++      buflen = needed;
++    }
++
++  return __sha512_crypt_r (key, salt, buffer, buflen);
++}
++
++#ifndef _LIBC
++static void
++__attribute__ ((__destructor__))
++free_mem (void)
++{
++  free (buffer);
++}
++#endif
+--- libc/crypt/sha512.c        1 Jan 1970 00:00:00 -0000
++++ libc/crypt/sha512.c        19 Sep 2007 20:36:37 -0000      1.1
+@@ -0,0 +1,336 @@
++/* Functions to compute SHA512 message digest of files or memory blocks.
++   according to the definition of SHA512 in FIPS 180-2.
++   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.  */
++
++/* Written by Ulrich Drepper <drepper@redhat.com>, 2007.  */
++
++#ifdef HAVE_CONFIG_H
++# include <config.h>
++#endif
++
++#include <endian.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include "sha512.h"
++
++#if __BYTE_ORDER == __LITTLE_ENDIAN
++# ifdef _LIBC
++#  include <byteswap.h>
++#  define SWAP(n) bswap_64 (n)
++# else
++#  define SWAP(n) \
++  (((n) << 56)                                        \
++   | (((n) & 0xff00) << 40)                   \
++   | (((n) & 0xff0000) << 24)                 \
++   | (((n) & 0xff000000) << 8)                        \
++   | (((n) >> 8) & 0xff000000)                        \
++   | (((n) >> 24) & 0xff0000)                 \
++   | (((n) >> 40) & 0xff00)                   \
++   | ((n) >> 56))
++# endif
++#else
++# define SWAP(n) (n)
++#endif
++
++
++/* This array contains the bytes used to pad the buffer to the next
++   64-byte boundary.  (FIPS 180-2:5.1.2)  */
++static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ...  */ };
++
++
++/* Constants for SHA512 from FIPS 180-2:4.2.3.  */
++static const uint64_t K[80] =
++  {
++    UINT64_C (0x428a2f98d728ae22), UINT64_C (0x7137449123ef65cd),
++    UINT64_C (0xb5c0fbcfec4d3b2f), UINT64_C (0xe9b5dba58189dbbc),
++    UINT64_C (0x3956c25bf348b538), UINT64_C (0x59f111f1b605d019),
++    UINT64_C (0x923f82a4af194f9b), UINT64_C (0xab1c5ed5da6d8118),
++    UINT64_C (0xd807aa98a3030242), UINT64_C (0x12835b0145706fbe),
++    UINT64_C (0x243185be4ee4b28c), UINT64_C (0x550c7dc3d5ffb4e2),
++    UINT64_C (0x72be5d74f27b896f), UINT64_C (0x80deb1fe3b1696b1),
++    UINT64_C (0x9bdc06a725c71235), UINT64_C (0xc19bf174cf692694),
++    UINT64_C (0xe49b69c19ef14ad2), UINT64_C (0xefbe4786384f25e3),
++    UINT64_C (0x0fc19dc68b8cd5b5), UINT64_C (0x240ca1cc77ac9c65),
++    UINT64_C (0x2de92c6f592b0275), UINT64_C (0x4a7484aa6ea6e483),
++    UINT64_C (0x5cb0a9dcbd41fbd4), UINT64_C (0x76f988da831153b5),
++    UINT64_C (0x983e5152ee66dfab), UINT64_C (0xa831c66d2db43210),
++    UINT64_C (0xb00327c898fb213f), UINT64_C (0xbf597fc7beef0ee4),
++    UINT64_C (0xc6e00bf33da88fc2), UINT64_C (0xd5a79147930aa725),
++    UINT64_C (0x06ca6351e003826f), UINT64_C (0x142929670a0e6e70),
++    UINT64_C (0x27b70a8546d22ffc), UINT64_C (0x2e1b21385c26c926),
++    UINT64_C (0x4d2c6dfc5ac42aed), UINT64_C (0x53380d139d95b3df),
++    UINT64_C (0x650a73548baf63de), UINT64_C (0x766a0abb3c77b2a8),
++    UINT64_C (0x81c2c92e47edaee6), UINT64_C (0x92722c851482353b),
++    UINT64_C (0xa2bfe8a14cf10364), UINT64_C (0xa81a664bbc423001),
++    UINT64_C (0xc24b8b70d0f89791), UINT64_C (0xc76c51a30654be30),
++    UINT64_C (0xd192e819d6ef5218), UINT64_C (0xd69906245565a910),
++    UINT64_C (0xf40e35855771202a), UINT64_C (0x106aa07032bbd1b8),
++    UINT64_C (0x19a4c116b8d2d0c8), UINT64_C (0x1e376c085141ab53),
++    UINT64_C (0x2748774cdf8eeb99), UINT64_C (0x34b0bcb5e19b48a8),
++    UINT64_C (0x391c0cb3c5c95a63), UINT64_C (0x4ed8aa4ae3418acb),
++    UINT64_C (0x5b9cca4f7763e373), UINT64_C (0x682e6ff3d6b2b8a3),
++    UINT64_C (0x748f82ee5defb2fc), UINT64_C (0x78a5636f43172f60),
++    UINT64_C (0x84c87814a1f0ab72), UINT64_C (0x8cc702081a6439ec),
++    UINT64_C (0x90befffa23631e28), UINT64_C (0xa4506cebde82bde9),
++    UINT64_C (0xbef9a3f7b2c67915), UINT64_C (0xc67178f2e372532b),
++    UINT64_C (0xca273eceea26619c), UINT64_C (0xd186b8c721c0c207),
++    UINT64_C (0xeada7dd6cde0eb1e), UINT64_C (0xf57d4f7fee6ed178),
++    UINT64_C (0x06f067aa72176fba), UINT64_C (0x0a637dc5a2c898a6),
++    UINT64_C (0x113f9804bef90dae), UINT64_C (0x1b710b35131c471b),
++    UINT64_C (0x28db77f523047d84), UINT64_C (0x32caab7b40c72493),
++    UINT64_C (0x3c9ebe0a15c9bebc), UINT64_C (0x431d67c49c100d4c),
++    UINT64_C (0x4cc5d4becb3e42b6), UINT64_C (0x597f299cfc657e2a),
++    UINT64_C (0x5fcb6fab3ad6faec), UINT64_C (0x6c44198c4a475817)
++  };
++
++
++/* Process LEN bytes of BUFFER, accumulating context into CTX.
++   It is assumed that LEN % 128 == 0.  */
++static void
++sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx)
++{
++  const uint64_t *words = buffer;
++  size_t nwords = len / sizeof (uint64_t);
++  uint64_t a = ctx->H[0];
++  uint64_t b = ctx->H[1];
++  uint64_t c = ctx->H[2];
++  uint64_t d = ctx->H[3];
++  uint64_t e = ctx->H[4];
++  uint64_t f = ctx->H[5];
++  uint64_t g = ctx->H[6];
++  uint64_t h = ctx->H[7];
++
++  /* First increment the byte count.  FIPS 180-2 specifies the possible
++     length of the file up to 2^128 bits.  Here we only compute the
++     number of bytes.  Do a double word increment.  */
++  ctx->total[0] += len;
++  if (ctx->total[0] < len)
++    ++ctx->total[1];
++
++  /* Process all bytes in the buffer with 128 bytes in each round of
++     the loop.  */
++  while (nwords > 0)
++    {
++      uint64_t W[80];
++      uint64_t a_save = a;
++      uint64_t b_save = b;
++      uint64_t c_save = c;
++      uint64_t d_save = d;
++      uint64_t e_save = e;
++      uint64_t f_save = f;
++      uint64_t g_save = g;
++      uint64_t h_save = h;
++
++      /* Operators defined in FIPS 180-2:4.1.2.  */
++#define Ch(x, y, z) ((x & y) ^ (~x & z))
++#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
++#define S0(x) (CYCLIC (x, 28) ^ CYCLIC (x, 34) ^ CYCLIC (x, 39))
++#define S1(x) (CYCLIC (x, 14) ^ CYCLIC (x, 18) ^ CYCLIC (x, 41))
++#define R0(x) (CYCLIC (x, 1) ^ CYCLIC (x, 8) ^ (x >> 7))
++#define R1(x) (CYCLIC (x, 19) ^ CYCLIC (x, 61) ^ (x >> 6))
++
++      /* It is unfortunate that C does not provide an operator for
++       cyclic rotation.  Hope the C compiler is smart enough.  */
++#define CYCLIC(w, s) ((w >> s) | (w << (64 - s)))
++
++      /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2.  */
++      for (unsigned int t = 0; t < 16; ++t)
++      {
++        W[t] = SWAP (*words);
++        ++words;
++      }
++      for (unsigned int t = 16; t < 80; ++t)
++      W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16];
++
++      /* The actual computation according to FIPS 180-2:6.3.2 step 3.  */
++      for (unsigned int t = 0; t < 80; ++t)
++      {
++        uint64_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
++        uint64_t T2 = S0 (a) + Maj (a, b, c);
++        h = g;
++        g = f;
++        f = e;
++        e = d + T1;
++        d = c;
++        c = b;
++        b = a;
++        a = T1 + T2;
++      }
++
++      /* Add the starting values of the context according to FIPS 180-2:6.3.2
++       step 4.  */
++      a += a_save;
++      b += b_save;
++      c += c_save;
++      d += d_save;
++      e += e_save;
++      f += f_save;
++      g += g_save;
++      h += h_save;
++
++      /* Prepare for the next round.  */
++      nwords -= 16;
++    }
++
++  /* Put checksum in context given as argument.  */
++  ctx->H[0] = a;
++  ctx->H[1] = b;
++  ctx->H[2] = c;
++  ctx->H[3] = d;
++  ctx->H[4] = e;
++  ctx->H[5] = f;
++  ctx->H[6] = g;
++  ctx->H[7] = h;
++}
++
++
++/* Initialize structure containing state of computation.
++   (FIPS 180-2:5.3.3)  */
++void
++__sha512_init_ctx (ctx)
++     struct sha512_ctx *ctx;
++{
++  ctx->H[0] = UINT64_C (0x6a09e667f3bcc908);
++  ctx->H[1] = UINT64_C (0xbb67ae8584caa73b);
++  ctx->H[2] = UINT64_C (0x3c6ef372fe94f82b);
++  ctx->H[3] = UINT64_C (0xa54ff53a5f1d36f1);
++  ctx->H[4] = UINT64_C (0x510e527fade682d1);
++  ctx->H[5] = UINT64_C (0x9b05688c2b3e6c1f);
++  ctx->H[6] = UINT64_C (0x1f83d9abfb41bd6b);
++  ctx->H[7] = UINT64_C (0x5be0cd19137e2179);
++
++  ctx->total[0] = ctx->total[1] = 0;
++  ctx->buflen = 0;
++}
++
++
++/* Process the remaining bytes in the internal buffer and the usual
++   prolog according to the standard and write the result to RESBUF.
++
++   IMPORTANT: On some systems it is required that RESBUF is correctly
++   aligned for a 32 bits value.  */
++void *
++__sha512_finish_ctx (ctx, resbuf)
++     struct sha512_ctx *ctx;
++     void *resbuf;
++{
++  /* Take yet unprocessed bytes into account.  */
++  uint64_t bytes = ctx->buflen;
++  size_t pad;
++
++  /* Now count remaining bytes.  */
++  ctx->total[0] += bytes;
++  if (ctx->total[0] < bytes)
++    ++ctx->total[1];
++
++  pad = bytes >= 112 ? 128 + 112 - bytes : 112 - bytes;
++  memcpy (&ctx->buffer[bytes], fillbuf, pad);
++
++  /* Put the 128-bit file length in *bits* at the end of the buffer.  */
++  *(uint64_t *) &ctx->buffer[bytes + pad + 8] = SWAP (ctx->total[0] << 3);
++  *(uint64_t *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) |
++                                                (ctx->total[0] >> 61));
++
++  /* Process last bytes.  */
++  sha512_process_block (ctx->buffer, bytes + pad + 16, ctx);
++
++  /* Put result from CTX in first 64 bytes following RESBUF.  */
++  for (unsigned int i = 0; i < 8; ++i)
++    ((uint64_t *) resbuf)[i] = SWAP (ctx->H[i]);
++
++  return resbuf;
++}
++
++
++void
++__sha512_process_bytes (buffer, len, ctx)
++     const void *buffer;
++     size_t len;
++     struct sha512_ctx *ctx;
++{
++  /* When we already have some bits in our internal buffer concatenate
++     both inputs first.  */
++  if (ctx->buflen != 0)
++    {
++      size_t left_over = ctx->buflen;
++      size_t add = 256 - left_over > len ? len : 256 - left_over;
++
++      memcpy (&ctx->buffer[left_over], buffer, add);
++      ctx->buflen += add;
++
++      if (ctx->buflen > 128)
++      {
++        sha512_process_block (ctx->buffer, ctx->buflen & ~127, ctx);
++
++        ctx->buflen &= 127;
++        /* The regions in the following copy operation cannot overlap.  */
++        memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~127],
++                ctx->buflen);
++      }
++
++      buffer = (const char *) buffer + add;
++      len -= add;
++    }
++
++  /* Process available complete blocks.  */
++  if (len >= 128)
++    {
++#if !_STRING_ARCH_unaligned
++/* To check alignment gcc has an appropriate operator.  Other
++   compilers don't.  */
++# if __GNUC__ >= 2
++#  define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint64_t) != 0)
++# else
++#  define UNALIGNED_P(p) (((uintptr_t) p) % sizeof (uint64_t) != 0)
++# endif
++      if (UNALIGNED_P (buffer))
++      while (len > 128)
++        {
++          sha512_process_block (memcpy (ctx->buffer, buffer, 128), 128,
++                                  ctx);
++          buffer = (const char *) buffer + 128;
++          len -= 128;
++        }
++      else
++#endif
++      {
++        sha512_process_block (buffer, len & ~127, ctx);
++        buffer = (const char *) buffer + (len & ~127);
++        len &= 127;
++      }
++    }
++
++  /* Move remaining bytes into internal buffer.  */
++  if (len > 0)
++    {
++      size_t left_over = ctx->buflen;
++
++      memcpy (&ctx->buffer[left_over], buffer, len);
++      left_over += len;
++      if (left_over >= 128)
++      {
++        sha512_process_block (ctx->buffer, 128, ctx);
++        left_over -= 128;
++        memcpy (ctx->buffer, &ctx->buffer[128], left_over);
++      }
++      ctx->buflen = left_over;
++    }
++}
+--- libc/crypt/sha512.h        1 Jan 1970 00:00:00 -0000
++++ libc/crypt/sha512.h        19 Sep 2007 20:36:43 -0000      1.1
+@@ -0,0 +1,58 @@
++/* Declaration of functions and data types used for SHA512 sum computing
++   library functions.
++   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.  */
++
++#ifndef _SHA512_H
++#define _SHA512_H 1
++
++#include <limits.h>
++#include <stdint.h>
++#include <stdio.h>
++
++
++/* Structure to save state of computation between the single steps.  */
++struct sha512_ctx
++{
++  uint64_t H[8];
++
++  uint64_t total[2];
++  uint64_t buflen;
++  char buffer[256] __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
++};
++
++/* Initialize structure containing state of computation.
++   (FIPS 180-2: 5.3.3)  */
++extern void __sha512_init_ctx (struct sha512_ctx *ctx) __THROW;
++
++/* Starting with the result of former calls of this function (or the
++   initialization function update the context for the next LEN bytes
++   starting at BUFFER.
++   It is NOT required that LEN is a multiple of 128.  */
++extern void __sha512_process_bytes (const void *buffer, size_t len,
++                                  struct sha512_ctx *ctx) __THROW;
++
++/* Process the remaining bytes in the buffer and put result from CTX
++   in first 64 bytes following RESBUF.
++
++   IMPORTANT: On some systems it is required that RESBUF is correctly
++   aligned for a 64 bits value.  */
++extern void *__sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf)
++  __THROW;
++
++#endif /* sha512.h */
+--- libc/crypt/sha512c-test.c  1 Jan 1970 00:00:00 -0000
++++ libc/crypt/sha512c-test.c  28 Oct 2007 19:46:43 -0000      1.2
+@@ -0,0 +1,63 @@
++#include <crypt.h>
++#include <stdio.h>
++#include <string.h>
++
++static const struct
++{
++  const char *salt;
++  const char *input;
++  const char *expected;
++} tests[] =
++{
++  { "$6$saltstring", "Hello world!",
++    "$6$saltstring$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJu"
++    "esI68u4OTLiBFdcbYEdFCoEOfaS35inz1" },
++  { "$6$rounds=10000$saltstringsaltstring", "Hello world!",
++    "$6$rounds=10000$saltstringsaltst$OW1/O6BYHV6BcXZu8QVeXbDWra3Oeqh0sb"
++    "HbbMCVNSnCM/UrjmM0Dp8vOuZeHBy/YTBmSK6H9qs/y3RnOaw5v." },
++  { "$6$rounds=5000$toolongsaltstring", "This is just a test",
++    "$6$rounds=5000$toolongsaltstrin$lQ8jolhgVRVhY4b5pZKaysCLi0QBxGoNeKQ"
++    "zQ3glMhwllF7oGDZxUhx1yxdYcz/e1JSbq3y6JMxxl8audkUEm0" },
++  { "$6$rounds=1400$anotherlongsaltstring",
++    "a very much longer text to encrypt.  This one even stretches over more"
++    "than one line.",
++    "$6$rounds=1400$anotherlongsalts$POfYwTEok97VWcjxIiSOjiykti.o/pQs.wP"
++    "vMxQ6Fm7I6IoYN3CmLs66x9t0oSwbtEW7o7UmJEiDwGqd8p4ur1" },
++  { "$6$rounds=77777$short",
++    "we have a short salt string but not a short password",
++    "$6$rounds=77777$short$WuQyW2YR.hBNpjjRhpYD/ifIw05xdfeEyQoMxIXbkvr0g"
++    "ge1a1x3yRULJ5CCaUeOxFmtlcGZelFl5CxtgfiAc0" },
++  { "$6$rounds=123456$asaltof16chars..", "a short string",
++    "$6$rounds=123456$asaltof16chars..$BtCwjqMJGx5hrJhZywWvt0RLE8uZ4oPwc"
++    "elCjmw2kSYu.Ec6ycULevoBK25fs2xXgMNrCzIMVcgEJAstJeonj1" },
++  { "$6$rounds=10$roundstoolow", "the minimum number is still observed",
++    "$6$rounds=1000$roundstoolow$kUMsbe306n21p9R.FRkW3IGn.S9NPN0x50YhH1x"
++    "hLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX." },
++};
++#define ntests (sizeof (tests) / sizeof (tests[0]))
++
++
++static int
++do_test (void)
++{
++  int result = 0;
++  int i;
++
++  for (i = 0; i < ntests; ++i)
++    {
++      char *cp = crypt (tests[i].input, tests[i].salt);
++
++      if (strcmp (cp, tests[i].expected) != 0)
++      {
++        printf ("test %d: expected \"%s\", got \"%s\"\n",
++                i, tests[i].expected, cp);
++        result = 1;
++      }
++    }
++
++  return result;
++}
++
++#define TIMEOUT 6
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/crypt/sha512test.c    1 Jan 1970 00:00:00 -0000
++++ libc/crypt/sha512test.c    19 Sep 2007 20:37:02 -0000      1.1
+@@ -0,0 +1,113 @@
++#include <string.h>
++#include "sha512.h"
++
++static const struct
++{
++  const char *input;
++  const char result[64];
++} tests[] =
++  {
++    /* Test vectors from FIPS 180-2: appendix C.1.  */
++    { "abc",
++      "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31"
++      "\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a"
++      "\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd"
++      "\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f" },
++    /* Test vectors from FIPS 180-2: appendix C.2.  */
++    { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
++      "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
++      "\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14\x3f"
++      "\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88\x90\x18"
++      "\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4\xb5\x43\x3a"
++      "\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b\x87\x4b\xe9\x09" },
++    /* Test vectors from the NESSIE project.  */
++    { "",
++      "\xcf\x83\xe1\x35\x7e\xef\xb8\xbd\xf1\x54\x28\x50\xd6\x6d\x80\x07"
++      "\xd6\x20\xe4\x05\x0b\x57\x15\xdc\x83\xf4\xa9\x21\xd3\x6c\xe9\xce"
++      "\x47\xd0\xd1\x3c\x5d\x85\xf2\xb0\xff\x83\x18\xd2\x87\x7e\xec\x2f"
++      "\x63\xb9\x31\xbd\x47\x41\x7a\x81\xa5\x38\x32\x7a\xf9\x27\xda\x3e" },
++    { "a",
++      "\x1f\x40\xfc\x92\xda\x24\x16\x94\x75\x09\x79\xee\x6c\xf5\x82\xf2"
++      "\xd5\xd7\xd2\x8e\x18\x33\x5d\xe0\x5a\xbc\x54\xd0\x56\x0e\x0f\x53"
++      "\x02\x86\x0c\x65\x2b\xf0\x8d\x56\x02\x52\xaa\x5e\x74\x21\x05\x46"
++      "\xf3\x69\xfb\xbb\xce\x8c\x12\xcf\xc7\x95\x7b\x26\x52\xfe\x9a\x75" },
++    { "message digest",
++      "\x10\x7d\xbf\x38\x9d\x9e\x9f\x71\xa3\xa9\x5f\x6c\x05\x5b\x92\x51"
++      "\xbc\x52\x68\xc2\xbe\x16\xd6\xc1\x34\x92\xea\x45\xb0\x19\x9f\x33"
++      "\x09\xe1\x64\x55\xab\x1e\x96\x11\x8e\x8a\x90\x5d\x55\x97\xb7\x20"
++      "\x38\xdd\xb3\x72\xa8\x98\x26\x04\x6d\xe6\x66\x87\xbb\x42\x0e\x7c" },
++    { "abcdefghijklmnopqrstuvwxyz",
++      "\x4d\xbf\xf8\x6c\xc2\xca\x1b\xae\x1e\x16\x46\x8a\x05\xcb\x98\x81"
++      "\xc9\x7f\x17\x53\xbc\xe3\x61\x90\x34\x89\x8f\xaa\x1a\xab\xe4\x29"
++      "\x95\x5a\x1b\xf8\xec\x48\x3d\x74\x21\xfe\x3c\x16\x46\x61\x3a\x59"
++      "\xed\x54\x41\xfb\x0f\x32\x13\x89\xf7\x7f\x48\xa8\x79\xc7\xb1\xf1" },
++    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
++      "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a\x0c\xed\x7b\xeb\x8e\x08\xa4\x16"
++      "\x57\xc1\x6e\xf4\x68\xb2\x28\xa8\x27\x9b\xe3\x31\xa7\x03\xc3\x35"
++      "\x96\xfd\x15\xc1\x3b\x1b\x07\xf9\xaa\x1d\x3b\xea\x57\x78\x9c\xa0"
++      "\x31\xad\x85\xc7\xa7\x1d\xd7\x03\x54\xec\x63\x12\x38\xca\x34\x45" },
++    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
++      "\x1e\x07\xbe\x23\xc2\x6a\x86\xea\x37\xea\x81\x0c\x8e\xc7\x80\x93"
++      "\x52\x51\x5a\x97\x0e\x92\x53\xc2\x6f\x53\x6c\xfc\x7a\x99\x96\xc4"
++      "\x5c\x83\x70\x58\x3e\x0a\x78\xfa\x4a\x90\x04\x1d\x71\xa4\xce\xab"
++      "\x74\x23\xf1\x9c\x71\xb9\xd5\xa3\xe0\x12\x49\xf0\xbe\xbd\x58\x94" },
++    { "123456789012345678901234567890123456789012345678901234567890"
++      "12345678901234567890",
++      "\x72\xec\x1e\xf1\x12\x4a\x45\xb0\x47\xe8\xb7\xc7\x5a\x93\x21\x95"
++      "\x13\x5b\xb6\x1d\xe2\x4e\xc0\xd1\x91\x40\x42\x24\x6e\x0a\xec\x3a"
++      "\x23\x54\xe0\x93\xd7\x6f\x30\x48\xb4\x56\x76\x43\x46\x90\x0c\xb1"
++      "\x30\xd2\xa4\xfd\x5d\xd1\x6a\xbb\x5e\x30\xbc\xb8\x50\xde\xe8\x43" }
++  };
++
++
++int
++main (void)
++{
++  struct sha512_ctx ctx;
++  char sum[64];
++  int result = 0;
++  int cnt;
++
++  for (cnt = 0; cnt < (int) (sizeof (tests) / sizeof (tests[0])); ++cnt)
++    {
++      __sha512_init_ctx (&ctx);
++      __sha512_process_bytes (tests[cnt].input, strlen (tests[cnt].input),
++                            &ctx);
++      __sha512_finish_ctx (&ctx, sum);
++      if (memcmp (tests[cnt].result, sum, 64) != 0)
++      {
++        printf ("test %d run %d failed\n", cnt, 1);
++        result = 1;
++      }
++
++      __sha512_init_ctx (&ctx);
++      for (int i = 0; tests[cnt].input[i] != '\0'; ++i)
++      __sha512_process_bytes (&tests[cnt].input[i], 1, &ctx);
++      __sha512_finish_ctx (&ctx, sum);
++      if (memcmp (tests[cnt].result, sum, 64) != 0)
++      {
++        printf ("test %d run %d failed\n", cnt, 2);
++        result = 1;
++      }
++    }
++
++  /* Test vector from FIPS 180-2: appendix C.3.  */
++  char buf[1000];
++  memset (buf, 'a', sizeof (buf));
++  __sha512_init_ctx (&ctx);
++  for (int i = 0; i < 1000; ++i)
++    __sha512_process_bytes (buf, sizeof (buf), &ctx);
++  __sha512_finish_ctx (&ctx, sum);
++  static const char expected[64] =
++    "\xe7\x18\x48\x3d\x0c\xe7\x69\x64\x4e\x2e\x42\xc7\xbc\x15\xb4\x63"
++    "\x8e\x1f\x98\xb1\x3b\x20\x44\x28\x56\x32\xa8\x03\xaf\xa9\x73\xeb"
++    "\xde\x0f\xf2\x44\x87\x7e\xa6\x0a\x4c\xb0\x43\x2c\xe5\x77\xc3\x1b"
++    "\xeb\x00\x9c\x5c\x2c\x49\xaa\x2e\x4e\xad\xb2\x17\xad\x8c\xc0\x9b";
++  if (memcmp (expected, sum, 64) != 0)
++    {
++      printf ("test %d failed\n", cnt);
++      result = 1;
++    }
++
++  return result;
++}
diff --git a/src/patches/glibc/glibc-rh230168.patch b/src/patches/glibc/glibc-rh230168.patch
new file mode 100644 (file)
index 0000000..b88ec5c
--- /dev/null
@@ -0,0 +1,229 @@
+2007-04-25  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/check_pf.c (make_request): Return -1 instead
+       of 0 after the out_fail label.
+
+2007-03-18  Jakub Jelinek  <jakub@redhat.com>
+
+       * nscd/gai.c: Include alloca.h.
+       (__libc_use_alloca): Define.
+
+2007-03-15  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/ifaddrs.c (__netlink_request): Never
+       reallocate the buffer, instead fail for MSG_TRUNC or for EBUSY
+       NLMSG_ERR.  Instead use a page sized buffer.
+       * sysdeps/unix/sysv/linux/check_pf.c (make_request): Use page sized
+       buffer.
+
+2007-03-02  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/ifaddrs.c (__netlink_request): Retry with
+       a new netlink socket if NLMSG_ERR -EBUSY is seen after some MSG_TRUNC
+       message.
+
+2007-02-27  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/ifaddrs.c (__netlink_request): Fix
+       memory reallocation.
+
+--- libc/sysdeps/unix/sysv/linux/ifaddrs.c     19 May 2006 07:46:03 -0000      1.16
++++ libc/sysdeps/unix/sysv/linux/ifaddrs.c     15 Mar 2007 20:02:11 -0000      1.19
+@@ -122,36 +122,36 @@ int
+ __netlink_request (struct netlink_handle *h, int type)
+ {
+   struct netlink_res *nlm_next;
+-  struct netlink_res **new_nlm_list;
+-  static volatile size_t buf_size = 4096;
+-  char *buf;
+   struct sockaddr_nl nladdr;
+   struct nlmsghdr *nlmh;
+   ssize_t read_len;
+   bool done = false;
+-  bool use_malloc = false;
+-  if (__netlink_sendreq (h, type) < 0)
+-    return -1;
++#ifdef PAGE_SIZE
++  /* Help the compiler optimize out the malloc call if PAGE_SIZE
++     is constant and smaller or equal to PTHREAD_STACK_MIN/4.  */
++  const size_t buf_size = PAGE_SIZE;
++#else
++  const size_t buf_size = __getpagesize ();
++#endif
++  bool use_malloc = false;
++  char *buf;
+-  size_t this_buf_size = buf_size;
+-  if (__libc_use_alloca (this_buf_size))
+-    buf = alloca (this_buf_size);
++  if (__libc_use_alloca (buf_size))
++    buf = alloca (buf_size);
+   else
+     {
+-      buf = malloc (this_buf_size);
++      buf = malloc (buf_size);
+       if (buf != NULL)
+       use_malloc = true;
+       else
+       goto out_fail;
+     }
+-  struct iovec iov = { buf, this_buf_size };
++  struct iovec iov = { buf, buf_size };
+-  if (h->nlm_list != NULL)
+-    new_nlm_list = &h->end_ptr->next;
+-  else
+-    new_nlm_list = &h->nlm_list;
++  if (__netlink_sendreq (h, type) < 0)
++    goto out_fail;
+   while (! done)
+     {
+@@ -171,48 +171,7 @@ __netlink_request (struct netlink_handle
+       continue;
+       if (__builtin_expect (msg.msg_flags & MSG_TRUNC, 0))
+-      {
+-        if (this_buf_size >= SIZE_MAX / 2)
+-          goto out_fail;
+-
+-        nlm_next = *new_nlm_list;
+-        while (nlm_next != NULL)
+-          {
+-            struct netlink_res *tmpptr;
+-
+-            tmpptr = nlm_next->next;
+-            free (nlm_next);
+-            nlm_next = tmpptr;
+-          }
+-        *new_nlm_list = NULL;
+-
+-        if (__libc_use_alloca (2 * this_buf_size))
+-          buf = extend_alloca (buf, this_buf_size, 2 * this_buf_size);
+-        else
+-          {
+-            this_buf_size *= 2;
+-
+-            char *new_buf = realloc (use_malloc ? buf : NULL, this_buf_size);
+-            if (new_buf == NULL)
+-              goto out_fail;
+-            new_buf = buf;
+-
+-            use_malloc = true;
+-          }
+-        buf_size = this_buf_size;
+-
+-        iov.iov_base = buf;
+-        iov.iov_len = this_buf_size;
+-
+-        /* Increase sequence number, so that we can distinguish
+-           between old and new request messages.  */
+-        h->seq++;
+-
+-        if (__netlink_sendreq (h, type) < 0)
+-          goto out_fail;
+-
+-        continue;
+-      }
++      goto out_fail;
+       size_t count = 0;
+       size_t remaining_len = read_len;
+--- libc/sysdeps/unix/sysv/linux/check_pf.c    24 Sep 2006 16:50:22 -0000      1.8
++++ libc/sysdeps/unix/sysv/linux/check_pf.c    25 Apr 2007 16:05:18 -0000      1.10
+@@ -17,6 +17,7 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
++#include <alloca.h>
+ #include <errno.h>
+ #include <ifaddrs.h>
+ #include <netdb.h>
+@@ -52,17 +53,38 @@ make_request (int fd, pid_t pid, bool *s
+   memset (&nladdr, '\0', sizeof (nladdr));
+   nladdr.nl_family = AF_NETLINK;
++#ifdef PAGE_SIZE
++  /* Help the compiler optimize out the malloc call if PAGE_SIZE
++     is constant and smaller or equal to PTHREAD_STACK_MIN/4.  */
++  const size_t buf_size = PAGE_SIZE;
++#else
++  const size_t buf_size = __getpagesize ();
++#endif
++  bool use_malloc = false;
++  char *buf;
++
++  if (__libc_use_alloca (buf_size))
++    buf = alloca (buf_size);
++  else
++    {
++      buf = malloc (buf_size);
++      if (buf != NULL)
++      use_malloc = true;
++      else
++      goto out_fail;
++    }
++
++  struct iovec iov = { buf, buf_size };
++
+   if (TEMP_FAILURE_RETRY (__sendto (fd, (void *) &req, sizeof (req), 0,
+                                   (struct sockaddr *) &nladdr,
+                                   sizeof (nladdr))) < 0)
+-    return -1;
++    goto out_fail;
+   *seen_ipv4 = false;
+   *seen_ipv6 = false;
+   bool done = false;
+-  char buf[4096];
+-  struct iovec iov = { buf, sizeof (buf) };
+   do
+     {
+@@ -76,10 +98,10 @@ make_request (int fd, pid_t pid, bool *s
+       ssize_t read_len = TEMP_FAILURE_RETRY (__recvmsg (fd, &msg, 0));
+       if (read_len < 0)
+-      return -1;
++      goto out_fail;
+       if (msg.msg_flags & MSG_TRUNC)
+-      return -1;
++      goto out_fail;
+       struct nlmsghdr *nlmh;
+       for (nlmh = (struct nlmsghdr *) buf;
+@@ -117,7 +139,14 @@ make_request (int fd, pid_t pid, bool *s
+   __close (fd);
++  if (use_malloc)
++    free (buf);
+   return 0;
++
++out_fail:
++  if (use_malloc)
++    free (buf);
++  return -1;
+ }
+--- libc/nscd/gai.c    14 Jan 2007 05:23:23 -0000      1.5
++++ libc/nscd/gai.c    18 Mar 2007 17:55:48 -0000      1.6
+@@ -1,3 +1,4 @@
++#include <alloca.h>
+ /* This file uses the getaddrinfo code but it compiles it without NSCD
+    support.  We just need a few symbol renames.  */
+ #define __getservbyname_r getservbyname_r
+@@ -8,6 +9,8 @@
+ #define __bind bind
+ #define __sendto sendto
+ #define __strchrnul strchrnul
++/* nscd uses 1MB or 2MB thread stacks.  */
++#define __libc_use_alloca(size) (size <= __MAX_ALLOCA_CUTOFF)
+ #include <getaddrinfo.c>
diff --git a/src/patches/glibc/glibc-rh230197.patch b/src/patches/glibc/glibc-rh230197.patch
new file mode 100644 (file)
index 0000000..64d810f
--- /dev/null
@@ -0,0 +1,22 @@
+2007-02-25  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Reset refcntr in
+       new thread, don't just decrement it.
+       Patch by Suzuki K P <suzuki@in.ibm.com>.
+
+--- libc/nptl/sysdeps/unix/sysv/linux/fork.c   20 Dec 2003 23:37:13 -0000      1.11
++++ libc/nptl/sysdeps/unix/sysv/linux/fork.c   25 Feb 2007 21:43:28 -0000      1.12
+@@ -167,8 +167,11 @@ __libc_fork (void)
+           allp->handler->child_handler ();
+         /* Note that we do not have to wake any possible waiter.
+-           This is the only thread in the new process.  */
+-        --allp->handler->refcntr;
++           This is the only thread in the new process.  The count
++           may have been bumped up by other threads doing a fork.
++           We reset it to 1, to avoid waiting for non-existing
++           thread(s) to release the count.  */
++        allp->handler->refcntr = 1;
+         /* XXX We could at this point look through the object pool
+            and mark all objects not on the __fork_handlers list as
diff --git a/src/patches/glibc/glibc-rh233460.patch b/src/patches/glibc/glibc-rh233460.patch
new file mode 100644 (file)
index 0000000..4fb9638
--- /dev/null
@@ -0,0 +1,725 @@
+2007-04-05  Jakub Jelinek  <jakub@redhat.com>
+
+       * nis/nis_call.c (__nisfind_server): Replace (*dir)->do_servers
+       with obj->do_servers after first_shoot.
+
+2007-03-01  Jakub Jelinek  <jakub@redhat.com>
+
+       * nis/nis_call.c: Include bits/libc-lock.h, sys/stat.h, unistd.h.
+       (nis_server_cache, nis_server_cache_lock, nis_cold_start_mtime): New
+       variables.
+       (nis_server_cache_search, nis_server_cache_add): New functions.
+       (__nisfind_server): Use them.  Add dbp and flags argument, if
+       call __nisbind_create.
+       (__nisbind_create): Add server_used and current_ep arguments,
+       only call __nis_findfastest if server_used is ~0.
+       (__do_niscall2, __prepare_niscall): Adjust callers.
+       (ckey_cache, ckey_cache_size, ckey_cache_allocated, ckey_cache_pid,
+       ckey_cache_euid, ckey_cache_lock): New variables.
+       (get_ckey): New function.
+       (__nisbind_connect): If not dbp->use_udp, pass IPPROTO_TCP to
+       __pmap_getnisport.  Save __pmap_getnisport result in
+       dbp->addr.sin_port if non-zero.  Use get_ckey to create conversation
+       key.
+       * nis/nis_lookup.c (nis_lookup): Likewise.
+       * nis/nis_table.c (nis_list): Likewise.
+       * nis/rpcsvc/nislib.h (__nisbind_create, __nisfind_server): Adjust
+       prototypes.
+
+       * nis/nss_nisplus/nisplus-pwd.c (_nss_nisplus_getpwnam_r,
+       _nss_nisplus_getpwuid_r): Pass USE_DGRAM flag to nis_list.
+       * nis/nss_nisplus/nisplus-service.c (_nss_nisplus_getservbyname_r,
+       _nss_nisplus_getservbyport_r): Likewise.
+       * nis/nss_nisplus/nisplus-network.c (_nss_nisplus_getnetbyname_r,
+       _nss_nisplus_getnetbyaddr_r): Likewise.
+       * nis/nss_nisplus/nisplus-spwd.c (_nss_nisplus_getspnam_r): Likewise.
+       * nis/nss_nisplus/nisplus-ethers.c (_nss_nisplus_gethostton_r,
+       _nss_nisplus_getntohost_r): Likewise.
+       * nis/nss_nisplus/nisplus-rpc.c (_nss_nisplus_getrpcbyname_r,
+       _nss_nisplus_getrpcbynumber_r): Likewise.
+
+--- libc/nis/nss_nisplus/nisplus-pwd.c.jj      2006-05-20 21:20:19.000000000 +0200
++++ libc/nis/nss_nisplus/nisplus-pwd.c 2007-03-01 13:45:32.000000000 +0100
+@@ -311,7 +311,7 @@ _nss_nisplus_getpwnam_r (const char *nam
+   snprintf (buf, sizeof (buf), "[name=%s],%s", name, pwd_tablename_val);
+-  result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++  result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM, NULL, NULL);
+   if (result == NULL)
+     {
+@@ -370,7 +370,7 @@ _nss_nisplus_getpwuid_r (const uid_t uid
+   snprintf (buf, sizeof (buf), "[uid=%lu],%s",
+           (unsigned long int) uid, pwd_tablename_val);
+-  result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++  result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM, NULL, NULL);
+   if (result == NULL)
+     {
+--- libc/nis/nss_nisplus/nisplus-service.c.jj  2006-04-30 07:44:23.000000000 +0200
++++ libc/nis/nss_nisplus/nisplus-service.c     2007-03-01 13:45:32.000000000 +0100
+@@ -322,7 +322,8 @@ _nss_nisplus_getservbyname_r (const char
+      for the next search */
+   snprintf (buf, sizeof (buf), "[name=%s,proto=%s],%s", name, protocol,
+           tablename_val);
+-  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM,
++                               NULL, NULL);
+   if (result != NULL)
+     {
+@@ -351,7 +352,8 @@ _nss_nisplus_getservbyname_r (const char
+       }
+       nis_freeresult (result);
+-      result = nis_list (bufptr, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++      result = nis_list (bufptr, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM,
++                       NULL, NULL);
+     }
+   if (result == NULL)
+@@ -420,7 +422,8 @@ _nss_nisplus_getservbyport_r (const int 
+   snprintf (buf, sizeof (buf), "[port=%d,proto=%s],%s",
+           number, protocol, tablename_val);
+-  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM,
++                               NULL, NULL);
+   if (result == NULL)
+     {
+--- libc/nis/nss_nisplus/nisplus-network.c.jj  2006-04-30 07:44:23.000000000 +0200
++++ libc/nis/nss_nisplus/nisplus-network.c     2007-03-01 13:45:32.000000000 +0100
+@@ -338,7 +339,7 @@ _nss_nisplus_getnetbyname_r (const char 
+   /* Search at first in the alias list, and use the correct name
+      for the next search */
+   snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
+-  result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
++  result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH | USE_DGRAM, NULL, NULL);
+   if (result != NULL)
+     {
+@@ -366,7 +367,8 @@ _nss_nisplus_getnetbyname_r (const char 
+       }
+       nis_freeresult (result);
+-      result = nis_list (bufptr, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
++      result = nis_list (bufptr, FOLLOW_LINKS | FOLLOW_PATH | USE_DGRAM,
++                       NULL, NULL);
+     }
+   if (result == NULL)
+@@ -438,7 +440,8 @@ _nss_nisplus_getnetbyaddr_r (uint32_t ad
+     while (1)
+       {
+       snprintf (buf, sizeof (buf), "[addr=%s],%s", buf2, tablename_val);
+-      nis_result *result = nis_list (buf, EXPAND_NAME, NULL, NULL);
++      nis_result *result = nis_list (buf, EXPAND_NAME | USE_DGRAM,
++                                     NULL, NULL);
+       if (result == NULL)
+         {
+--- libc/nis/nss_nisplus/nisplus-spwd.c.jj     2006-04-30 07:44:23.000000000 +0200
++++ libc/nis/nss_nisplus/nisplus-spwd.c        2007-03-01 13:45:32.000000000 +0100
+@@ -182,7 +183,7 @@ _nss_nisplus_getspnam_r (const char *nam
+   snprintf (buf, sizeof (buf), "[name=%s],%s", name, pwd_tablename_val);
+-  result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++  result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM, NULL, NULL);
+   if (result == NULL)
+     {
+--- libc/nis/nss_nisplus/nisplus-ethers.c.jj   2006-04-30 07:44:23.000000000 +0200
++++ libc/nis/nss_nisplus/nisplus-ethers.c      2007-03-01 13:45:32.000000000 +0100
+@@ -256,7 +257,8 @@ _nss_nisplus_gethostton_r (const char *n
+   snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
+-  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM,
++                               NULL, NULL);
+   if (result == NULL)
+     {
+@@ -322,7 +324,8 @@ _nss_nisplus_getntohost_r (const struct 
+           addr->ether_addr_octet[4], addr->ether_addr_octet[5],
+           tablename_val);
+-  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM,
++                               NULL, NULL);
+   if (result == NULL)
+     {
+--- libc/nis/nss_nisplus/nisplus-rpc.c.jj      2006-04-30 07:44:23.000000000 +0200
++++ libc/nis/nss_nisplus/nisplus-rpc.c 2007-03-01 13:45:32.000000000 +0100
+@@ -315,7 +315,8 @@ _nss_nisplus_getrpcbyname_r (const char 
+   /* Search at first in the alias list, and use the correct name
+      for the next search */
+   snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
+-  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
++  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM,
++                               NULL, NULL);
+   if (result != NULL)
+     {
+@@ -342,7 +343,8 @@ _nss_nisplus_getrpcbyname_r (const char 
+       }
+       nis_freeresult (result);
+-      result = nis_list (bufptr, FOLLOW_PATH | FOLLOW_LINKS , NULL, NULL);
++      result = nis_list (bufptr, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM,
++                       NULL, NULL);
+     }
+   if (result == NULL)
+@@ -402,7 +404,8 @@ _nss_nisplus_getrpcbynumber_r (const int
+   snprintf (buf, sizeof (buf), "[number=%d],%s", number, tablename_val);
+-  nis_result *result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
++  nis_result *result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH | USE_DGRAM,
++                               NULL, NULL);
+   if (result == NULL)
+     {
+--- libc/nis/nis_lookup.c.jj   2006-08-07 18:02:48.000000000 +0200
++++ libc/nis/nis_lookup.c      2007-03-01 13:45:32.000000000 +0100
+@@ -127,18 +128,10 @@ nis_lookup (const_nis_name name, const u
+                       /* Otherwise __nisfind_server will not do anything.  */
+                       dir = NULL;
+-                      if (__nisfind_server (req.ns_name, 1, &dir)
++                      if (__nisfind_server (req.ns_name, 1, &dir, &bptr,
++                                            flags & ~MASTER_ONLY)
+                           != NIS_SUCCESS)
+                         goto out;
+-
+-                      if (__nisbind_create (&bptr,
+-                                            dir->do_servers.do_servers_val,
+-                                            dir->do_servers.do_servers_len,
+-                                            flags) != NIS_SUCCESS)
+-                        {
+-                          nis_free_directory (dir);
+-                          goto out;
+-                        }
+                     }
+                   else
+                     if (__nisbind_next (&bptr) != NIS_SUCCESS)
+--- libc/nis/nis_call.c.jj     2006-08-07 19:39:39.000000000 +0200
++++ libc/nis/nis_call.c        2007-03-01 15:23:07.000000000 +0100
+@@ -25,8 +26,11 @@
+ #include <rpc/auth.h>
+ #include <rpcsvc/nis.h>
+ #include <sys/socket.h>
++#include <sys/stat.h>
++#include <unistd.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
++#include <bits/libc-lock.h>
+ #include "nis_xdr.h"
+ #include "nis_intern.h"
+@@ -107,10 +111,79 @@ __nisbind_next (dir_binding *bind)
+ }
+ libnsl_hidden_def (__nisbind_next)
++static struct ckey_cache_entry
++{
++  struct in_addr inaddr;
++  in_port_t port;
++  unsigned int protocol;
++  des_block ckey;
++} *ckey_cache;
++static size_t ckey_cache_size;
++static size_t ckey_cache_allocated;
++static pid_t ckey_cache_pid;
++static uid_t ckey_cache_euid;
++__libc_lock_define_initialized (static, ckey_cache_lock)
++
++static bool_t
++get_ckey (des_block *ckey, struct sockaddr_in *addr, unsigned int protocol)
++{
++  size_t i;
++  pid_t pid = getpid ();
++  uid_t euid = geteuid ();
++  bool_t ret = FALSE;
++
++  __libc_lock_lock (ckey_cache_lock);
++
++  if (ckey_cache_pid != pid || ckey_cache_euid != euid)
++    {
++      ckey_cache_size = 0;
++      ckey_cache_pid = pid;
++      ckey_cache_euid = euid;
++    }
++
++  for (i = 0; i < ckey_cache_size; ++i)
++    if (ckey_cache[i].port == addr->sin_port
++      && ckey_cache[i].protocol == protocol
++      && memcmp (&ckey_cache[i].inaddr, &addr->sin_addr,
++                 sizeof (addr->sin_addr)) == 0)
++      {
++      *ckey = ckey_cache[i].ckey;
++      ret = TRUE;
++      break;
++      }
++
++  if (!ret && key_gendes (ckey) >= 0)
++    {
++      ret = TRUE;
++      /* Don't grow the cache indefinitely.  */
++      if (ckey_cache_size == 256)
++      ckey_cache_size = 0;
++      if (ckey_cache_size == ckey_cache_allocated)
++      {
++        size_t size = ckey_cache_allocated ? ckey_cache_allocated * 2 : 16;
++        struct ckey_cache_entry *new_cache
++          = realloc (ckey_cache, size * sizeof (*ckey_cache));
++        if (new_cache != NULL)
++          {
++            ckey_cache = new_cache;
++            ckey_cache_allocated = size;
++          }
++      }
++      ckey_cache[ckey_cache_size].inaddr = addr->sin_addr;
++      ckey_cache[ckey_cache_size].port = addr->sin_port;
++      ckey_cache[ckey_cache_size].protocol = protocol;
++      ckey_cache[ckey_cache_size++].ckey = *ckey;
++    }
++
++  __libc_lock_unlock (ckey_cache_lock);
++  return ret;
++}
++
+ nis_error
+ __nisbind_connect (dir_binding *dbp)
+ {
+   nis_server *serv;
++  u_short port;
+   if (dbp == NULL)
+     return NIS_FAIL;
+@@ -128,9 +202,12 @@ __nisbind_connect (dir_binding *dbp)
+   /* Check, if the host is online and rpc.nisd is running. Much faster
+      then the clnt*_create functions: */
+-  if (__pmap_getnisport (&dbp->addr, NIS_PROG, NIS_VERSION, IPPROTO_UDP) == 0)
++  port = __pmap_getnisport (&dbp->addr, NIS_PROG, NIS_VERSION,
++                          dbp->use_udp ? IPPROTO_UDP : IPPROTO_TCP);
++  if (port == 0)
+     return NIS_RPCERROR;
++  dbp->addr.sin_port = htons (port);
+   dbp->socket = RPC_ANYSOCK;
+   if (dbp->use_udp)
+     dbp->clnt = clntudp_create (&dbp->addr, NIS_PROG, NIS_VERSION,
+@@ -153,17 +230,16 @@ __nisbind_connect (dir_binding *dbp)
+       {
+         char netname[MAXNETNAMELEN + 1];
+         char *p;
++        des_block ckey;
+-        p = stpcpy (netname, "unix.");
++        p = stpcpy (netname, "unix@");
+         strncpy (p, serv->name, MAXNETNAMELEN - 5);
+         netname[MAXNETNAMELEN] = '\0';
+-        // XXX What is this supposed to do?  If we really want to replace
+-        // XXX the first dot, then we might as well use unix@ as the
+-        // XXX prefix string.  --drepper
+-        p = strchr (netname, '.');
+-        *p = '@';
+-        dbp->clnt->cl_auth =
+-          authdes_pk_create (netname, &serv->pkey, 300, NULL, NULL);
++        dbp->clnt->cl_auth = NULL;
++        if (get_ckey (&ckey, &dbp->addr,
++                      dbp->use_udp ? IPPROTO_UDP : IPPROTO_TCP))
++          dbp->clnt->cl_auth =
++            authdes_pk_create (netname, &serv->pkey, 300, NULL, &ckey);
+         if (!dbp->clnt->cl_auth)
+           dbp->clnt->cl_auth = authunix_create_default ();
+       }
+@@ -177,7 +253,8 @@ libnsl_hidden_def (__nisbind_connect)
+ nis_error
+ __nisbind_create (dir_binding *dbp, const nis_server *serv_val,
+-                unsigned int serv_len, unsigned int flags)
++                unsigned int serv_len, unsigned int server_used,
++                unsigned int current_ep, unsigned int flags)
+ {
+   dbp->clnt = NULL;
+@@ -203,8 +280,16 @@ __nisbind_create (dir_binding *dbp, cons
+   dbp->trys = 1;
+   dbp->class = -1;
+-  if (__nis_findfastest (dbp) < 1)
+-    return NIS_NAMEUNREACHABLE;
++  if (server_used == ~0)
++    {
++      if (__nis_findfastest (dbp) < 1)
++      return NIS_NAMEUNREACHABLE;
++    }
++  else
++    {
++      dbp->server_used = server_used;
++      dbp->current_ep = current_ep;
++    }
+   return NIS_SUCCESS;
+ }
+@@ -306,7 +391,7 @@ __do_niscall2 (const nis_server *server,
+   if (flags & MASTER_ONLY)
+     server_len = 1;
+-  status = __nisbind_create (&dbp, server, server_len, flags);
++  status = __nisbind_create (&dbp, server, server_len, ~0, ~0, flags);
+   if (status != NIS_SUCCESS)
+     return status;
+@@ -499,42 +584,221 @@ first_shoot (const_nis_name name, int se
+   return obj;
+ }
++static struct nis_server_cache
++{
++  int search_parent_first;
++  int uses;
++  unsigned int size;
++  unsigned int server_used;
++  unsigned int current_ep;
++  time_t expires;
++  char name[];
++} *nis_server_cache[16];
++static time_t nis_cold_start_mtime;
++__libc_lock_define_initialized (static, nis_server_cache_lock)
++
++static directory_obj *
++nis_server_cache_search (const_nis_name name, int search_parent_first,
++                       unsigned int *server_used, unsigned int *current_ep,
++                       struct timeval *now)
++{
++  directory_obj *ret = NULL;
++  int i;
++  char *addr;
++  XDR xdrs;
++  struct stat64 st;
++
++  if (stat64 ("/var/nis/NIS_COLD_START", &st) < 0)
++    st.st_mtime = nis_cold_start_mtime + 1;
++
++  __libc_lock_lock (nis_server_cache_lock);
++
++  for (i = 0; i < 16; ++i)
++    if (nis_server_cache[i] == NULL)
++      continue;
++    else if (st.st_mtime != nis_cold_start_mtime
++           || now->tv_sec > nis_server_cache[i]->expires)
++      {
++      free (nis_server_cache[i]);
++      nis_server_cache[i] = NULL;
++      }
++    else if (nis_server_cache[i]->search_parent_first == search_parent_first
++           && strcmp (nis_server_cache[i]->name, name) == 0)
++      {
++      ret = calloc (1, sizeof (directory_obj));
++      if (ret == NULL)
++        break;
++
++      addr = rawmemchr (nis_server_cache[i]->name, '\0') + 8;
++      addr = (char *) ((uintptr_t) addr & ~(uintptr_t) 7);
++      xdrmem_create (&xdrs, addr, nis_server_cache[i]->size, XDR_DECODE);
++      if (!_xdr_directory_obj (&xdrs, ret))
++        {
++          xdr_destroy (&xdrs);
++          free (ret);
++          ret = NULL;
++          free (nis_server_cache[i]);
++          nis_server_cache[i] = NULL;
++          break;
++        }
++      xdr_destroy (&xdrs);
++      *server_used = nis_server_cache[i]->server_used;
++      *current_ep = nis_server_cache[i]->current_ep;
++      break;
++      }
++
++  nis_cold_start_mtime = st.st_mtime;
++
++  __libc_lock_unlock (nis_server_cache_lock);
++  return ret;
++}
++
++static void
++nis_server_cache_add (const_nis_name name, int search_parent_first,
++                    directory_obj *dir, unsigned int server_used,
++                    unsigned int current_ep, struct timeval *now)
++{
++  struct nis_server_cache **loc;
++  struct nis_server_cache *new;
++  struct nis_server_cache *old;
++  int i;
++  char *addr;
++  unsigned int size;
++  XDR xdrs;
++
++  if (dir == NULL)
++    return;
++
++  size = xdr_sizeof ((xdrproc_t) _xdr_directory_obj, (char *) dir);
++  new = calloc (1, sizeof (*new) + strlen (name) + 8 + size);
++  if (new == NULL)
++    return;
++  new->search_parent_first = search_parent_first;
++  new->uses = 1;
++  new->expires = now->tv_sec + dir->do_ttl;
++  new->size = size;
++  new->server_used = server_used;
++  new->current_ep = current_ep;
++  addr = stpcpy (new->name, name) + 8;
++  addr = (char *) ((uintptr_t) addr & ~(uintptr_t) 7);
++
++  xdrmem_create(&xdrs, addr, size, XDR_ENCODE);
++  if (!_xdr_directory_obj (&xdrs, dir))
++    {
++      xdr_destroy (&xdrs);
++      free (new);
++      return;
++    }
++  xdr_destroy (&xdrs);
++
++  __libc_lock_lock (nis_server_cache_lock);
++
++  /* Choose which entry should be evicted from the cache.  */
++  loc = &nis_server_cache[0];
++  if (*loc != NULL)
++    for (i = 1; i < 16; ++i)
++      if (nis_server_cache[i] == NULL)
++      {
++        loc = &nis_server_cache[i];
++        break;
++      }
++      else if ((*loc)->uses > nis_server_cache[i]->uses
++             || ((*loc)->uses == nis_server_cache[i]->uses
++                 && (*loc)->expires > nis_server_cache[i]->expires))
++      loc = &nis_server_cache[i];
++  old = *loc;
++  *loc = new;
++
++  __libc_lock_unlock (nis_server_cache_lock);
++  free (old);
++}
++
+ nis_error
+ __nisfind_server (const_nis_name name, int search_parent_first,
+-                directory_obj **dir)
++                directory_obj **dir, dir_binding *dbp, unsigned int flags)
+ {
++  nis_error result = NIS_SUCCESS;
++  nis_error status;
++  directory_obj *obj;
++  struct timeval now;
++  unsigned int server_used = ~0;
++  unsigned int current_ep = ~0;
++
+   if (name == NULL)
+     return NIS_BADNAME;
+-#if 0
+-  /* Search in local cache. In the moment, we ignore the fastest server */
+-  if (!(flags & NO_CACHE))
+-    dir = __nis_cache_search (name, flags, &cinfo);
+-#endif
++  if (*dir != NULL)
++    return NIS_SUCCESS;
+-  nis_error result = NIS_SUCCESS;
+-  if (*dir == NULL)
++  (void) gettimeofday (&now, NULL);
++
++  if ((flags & NO_CACHE) == 0)
++    *dir = nis_server_cache_search (name, search_parent_first, &server_used,
++                                  &current_ep, &now);
++  if (*dir != NULL)
+     {
+-      nis_error status;
+-      directory_obj *obj;
++      unsigned int server_len = (*dir)->do_servers.do_servers_len;
++      if (flags & MASTER_ONLY)
++      {
++        server_len = 1;
++        if (server_used != 0)
++          {
++            server_used = ~0;
++            current_ep = ~0;
++          }
++      }
++      result = __nisbind_create (dbp, (*dir)->do_servers.do_servers_val,
++                               server_len, server_used, current_ep, flags);
++      if (result != NIS_SUCCESS)
++      {
++        nis_free_directory (*dir);
++        *dir = NULL;
++      }
++      return result;
++    }
+-      *dir = readColdStartFile ();
+-      if (*dir == NULL)
+-      /* No /var/nis/NIS_COLD_START->no NIS+ installed.  */
+-      return NIS_UNAVAIL;
++  *dir = readColdStartFile ();
++  if (*dir == NULL)
++    /* No /var/nis/NIS_COLD_START->no NIS+ installed.  */
++    return NIS_UNAVAIL;
+-      /* Try at first, if servers in "dir" know our object */
+-      obj = first_shoot (name, search_parent_first, *dir);
++  /* Try at first, if servers in "dir" know our object */
++  obj = first_shoot (name, search_parent_first, *dir);
++  if (obj == NULL)
++    {
++      obj = rec_dirsearch (name, *dir, &status);
+       if (obj == NULL)
++      result = status;
++    }
++
++  if (result == NIS_SUCCESS)
++    {
++      unsigned int server_len = obj->do_servers.do_servers_len;
++      if (flags & MASTER_ONLY)
++      server_len = 1;
++      result = __nisbind_create (dbp, obj->do_servers.do_servers_val,
++                               server_len, ~0, ~0, flags);
++      if (result == NIS_SUCCESS)
+       {
+-        obj = rec_dirsearch (name, *dir, &status);
+-        if (obj == NULL)
+-          result = status;
++        if ((flags & MASTER_ONLY) == 0
++            || obj->do_servers.do_servers_len == 1)
++          {
++            server_used = dbp->server_used;
++            current_ep = dbp->current_ep;
++          }
++        if ((flags & NO_CACHE) == 0)
++          nis_server_cache_add (name, search_parent_first, obj,
++                                server_used, current_ep, &now);
++      }
++      else
++      {
++        nis_free_directory (obj);
++        obj = NULL;
+       }
+-
+-      *dir = obj;
+     }
++  *dir = obj;
++
+   return result;
+ }
+@@ -543,38 +807,19 @@ nis_error
+ __prepare_niscall (const_nis_name name, directory_obj **dirp,
+                  dir_binding *bptrp, unsigned int flags)
+ {
+-  nis_error retcode = __nisfind_server (name, 1, dirp);
++  nis_error retcode = __nisfind_server (name, 1, dirp, bptrp, flags);
+   if (__builtin_expect (retcode != NIS_SUCCESS, 0))
+     return retcode;
+-  nis_server *server;
+-  u_int server_len;
+-
+-  if (flags & MASTER_ONLY)
+-    {
+-      server = (*dirp)->do_servers.do_servers_val;
+-      server_len = 1;
+-    }
+-  else
+-    {
+-      server = (*dirp)->do_servers.do_servers_val;
+-      server_len = (*dirp)->do_servers.do_servers_len;
+-    }
+-
+-  retcode = __nisbind_create (bptrp, server, server_len, flags);
+-  if (retcode == NIS_SUCCESS)
+-    {
+-      do
+-      if (__nisbind_connect (bptrp) == NIS_SUCCESS)
+-        return NIS_SUCCESS;
+-      while (__nisbind_next (bptrp) == NIS_SUCCESS);
+-
+-      __nisbind_destroy (bptrp);
+-      memset (bptrp, '\0', sizeof (*bptrp));
++  do
++    if (__nisbind_connect (bptrp) == NIS_SUCCESS)
++      return NIS_SUCCESS;
++  while (__nisbind_next (bptrp) == NIS_SUCCESS);
+-      retcode = NIS_NAMEUNREACHABLE;
+-    }
++  __nisbind_destroy (bptrp);
++  memset (bptrp, '\0', sizeof (*bptrp));
++  retcode = NIS_NAMEUNREACHABLE;
+   nis_free_directory (*dirp);
+   *dirp = NULL;
+--- libc/nis/nis_table.c.jj    2006-10-09 09:46:37.000000000 +0200
++++ libc/nis/nis_table.c       2007-03-01 13:45:32.000000000 +0100
+@@ -274,21 +275,14 @@ nis_list (const_nis_name name, unsigned 
+       memset (res, '\0', sizeof (nis_result));
+       status = __nisfind_server (ibreq->ibr_name,
+-                               ibreq->ibr_srch.ibr_srch_val != NULL, &dir);
++                               ibreq->ibr_srch.ibr_srch_val != NULL,
++                               &dir, &bptr, flags & ~MASTER_ONLY);
+       if (status != NIS_SUCCESS)
+       {
+           NIS_RES_STATUS (res) = status;
+           goto fail3;
+       }
+-      status = __nisbind_create (&bptr, dir->do_servers.do_servers_val,
+-                               dir->do_servers.do_servers_len, flags);
+-      if (__builtin_expect (status != NIS_SUCCESS, 0))
+-        {
+-          NIS_RES_STATUS (res) = status;
+-        goto fail2;
+-        }
+-
+       while (__nisbind_connect (&bptr) != NIS_SUCCESS)
+       if (__builtin_expect (__nisbind_next (&bptr) != NIS_SUCCESS, 0))
+         {
+@@ -338,7 +332,6 @@ nis_list (const_nis_name name, unsigned 
+                   NIS_RES_STATUS (res) = NIS_NOMEMORY;
+                 fail:
+                   __nisbind_destroy (&bptr);
+-                fail2:
+                   nis_free_directory (dir);
+                 fail3:
+                   free (tablepath);
+--- libc/nis/rpcsvc/nislib.h.jj        2006-08-07 18:01:48.000000000 +0200
++++ libc/nis/rpcsvc/nislib.h   2007-03-01 13:45:32.000000000 +0100
+@@ -272,12 +272,13 @@ struct dir_binding
+ typedef struct dir_binding dir_binding;
+ extern nis_error __nisbind_create (dir_binding *, const nis_server *,
+-                                 unsigned int, unsigned int) __THROW;
++                                 unsigned int, unsigned int, unsigned int,
++                                 unsigned int) __THROW;
+ extern nis_error __nisbind_connect (dir_binding *) __THROW;
+ extern nis_error __nisbind_next (dir_binding *) __THROW;
+ extern void __nisbind_destroy (dir_binding *) __THROW;
+-extern nis_error __nisfind_server (const_nis_name, int, directory_obj **)
+-     __THROW;
++extern nis_error __nisfind_server (const_nis_name, int, directory_obj **,
++                                 dir_binding *, unsigned int) __THROW;
+ #endif
diff --git a/src/patches/glibc/glibc-rh235229.patch b/src/patches/glibc/glibc-rh235229.patch
new file mode 100644 (file)
index 0000000..cf44455
--- /dev/null
@@ -0,0 +1,225 @@
+2007-04-06  Jakub Jelinek  <jakub@redhat.com>
+
+       * nis/nis_domain_of.c (__nis_domain_of): New function.
+       * include/rpcsvc/nislib.h (__nis_domain_of): New prototype.
+       * nis/nis_lookup.c (nis_lookup): Use __nis_domain_of.
+       * nis/nis_call.c (rec_dirsearch): Likewise.
+       (first_shoot): Likewise.  Remove search_parent_first argument.
+       (struct nis_server_cache): Rename search_parent_first field
+       to search_parent.
+       (nis_server_cache_search, nis_server_cache_add): Rename
+       search_parent_first argument to search_parent.
+       (__nisfind_server): Likewise.  If search_parent, call
+       __nis_domain_of.
+
+--- libc/nis/nis_domain_of.c.jj        2001-07-06 00:55:36.000000000 -0400
++++ libc/nis/nis_domain_of.c   2007-04-06 11:03:41.000000000 -0400
+@@ -1,4 +1,4 @@
+-/* Copyright (c) 1997 Free Software Foundation, Inc.
++/* Copyright (c) 1997, 2007 Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+    Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+@@ -26,3 +26,17 @@ nis_domain_of (const_nis_name name)
+   return nis_domain_of_r (name, result, NIS_MAXNAMELEN);
+ }
++
++const_nis_name
++__nis_domain_of (const_nis_name name)
++{
++  const_nis_name cptr = strchr (name, '.');
++
++  if (cptr++ == NULL)
++    return "";
++
++  if (*cptr == '\0')
++    return ".";
++
++  return cptr;
++}
+--- libc/nis/nis_lookup.c.jj   2007-04-05 07:40:08.000000000 -0400
++++ libc/nis/nis_lookup.c      2007-04-06 11:13:17.000000000 -0400
+@@ -74,7 +74,6 @@ nis_lookup (const_nis_name name, const u
+       {
+         static const struct timeval RPCTIMEOUT = {10, 0};
+         enum clnt_stat result;
+-        char ndomain[strlen (req.ns_name) + 1];
+       again:
+         result = clnt_call (bptr.clnt, NIS_LOOKUP,
+@@ -136,10 +135,9 @@ nis_lookup (const_nis_name name, const u
+                     if (__nisbind_next (&bptr) != NIS_SUCCESS)
+                       {
+                         /* No more servers to search.  Try parent.  */
+-                        nis_domain_of_r (req.ns_name, ndomain,
+-                                         sizeof (ndomain));
++                        const char *ndomain = __nis_domain_of (req.ns_name);
+                         req.ns_name = strdupa (ndomain);
+-                        if (strcmp (ndomain, ".") == 0)
++                        if (strcmp (req.ns_name, ".") == 0)
+                           {
+                             NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
+                             goto out;
+--- libc/nis/nis_call.c.jj     2007-04-05 08:10:07.000000000 -0400
++++ libc/nis/nis_call.c        2007-04-06 11:31:30.000000000 -0400
+@@ -423,9 +423,7 @@ rec_dirsearch (const_nis_name name, dire
+     case HIGHER_NAME:
+       { /* We need data from a parent domain */
+       directory_obj *obj;
+-      char ndomain[strlen (dir->do_name) + 3];
+-
+-      nis_domain_of_r (dir->do_name, ndomain, sizeof (ndomain));
++      const char *ndomain = __nis_domain_of (dir->do_name);
+       /* The root server of our domain is a replica of the parent
+          domain ! (Now I understand why a root server must be a
+@@ -469,7 +467,7 @@ rec_dirsearch (const_nis_name name, dire
+       size_t namelen = strlen (name);
+       char leaf[namelen + 3];
+       char domain[namelen + 3];
+-      char ndomain[namelen + 3];
++      const char *ndomain;
+       char *cp;
+       strcpy (domain, name);
+@@ -482,8 +480,8 @@ rec_dirsearch (const_nis_name name, dire
+               return NULL;
+             }
+           nis_leaf_of_r (domain, leaf, sizeof (leaf));
+-          nis_domain_of_r (domain, ndomain, sizeof (ndomain));
+-          strcpy (domain, ndomain);
++          ndomain = __nis_domain_of (domain);
++          memmove (domain, ndomain, strlen (ndomain) + 1);
+         }
+       while (nis_dir_cmp (domain, dir->do_name) != SAME_NAME);
+@@ -536,29 +534,16 @@ rec_dirsearch (const_nis_name name, dire
+ /* We try to query the current server for the searched object,
+    maybe he know about it ? */
+ static directory_obj *
+-first_shoot (const_nis_name name, int search_parent_first, directory_obj *dir)
++first_shoot (const_nis_name name, directory_obj *dir)
+ {
+   directory_obj *obj = NULL;
+   fd_result *fd_res;
+   XDR xdrs;
+-  char domain[strlen (name) + 3];
+-#if 0
+   if (nis_dir_cmp (name, dir->do_name) == SAME_NAME)
+     return dir;
+-#endif
+-
+-  const char *search_name = name;
+-  if (search_parent_first)
+-    {
+-      nis_domain_of_r (name, domain, sizeof (domain));
+-      search_name = domain;
+-    }
+-
+-  if (nis_dir_cmp (search_name, dir->do_name) == SAME_NAME)
+-    return dir;
+-  fd_res = __nis_finddirectory (dir, search_name);
++  fd_res = __nis_finddirectory (dir, name);
+   if (fd_res == NULL)
+     return NULL;
+   if (fd_res->status == NIS_SUCCESS
+@@ -586,7 +571,7 @@ first_shoot (const_nis_name name, int se
+ static struct nis_server_cache
+ {
+-  int search_parent_first;
++  int search_parent;
+   int uses;
+   unsigned int size;
+   unsigned int server_used;
+@@ -598,7 +583,7 @@ static time_t nis_cold_start_mtime;
+ __libc_lock_define_initialized (static, nis_server_cache_lock)
+ static directory_obj *
+-nis_server_cache_search (const_nis_name name, int search_parent_first,
++nis_server_cache_search (const_nis_name name, int search_parent,
+                        unsigned int *server_used, unsigned int *current_ep,
+                        struct timeval *now)
+ {
+@@ -622,7 +607,7 @@ nis_server_cache_search (const_nis_name 
+       free (nis_server_cache[i]);
+       nis_server_cache[i] = NULL;
+       }
+-    else if (nis_server_cache[i]->search_parent_first == search_parent_first
++    else if (nis_server_cache[i]->search_parent == search_parent
+            && strcmp (nis_server_cache[i]->name, name) == 0)
+       {
+       ret = calloc (1, sizeof (directory_obj));
+@@ -654,7 +639,7 @@ nis_server_cache_search (const_nis_name 
+ }
+ static void
+-nis_server_cache_add (const_nis_name name, int search_parent_first,
++nis_server_cache_add (const_nis_name name, int search_parent,
+                     directory_obj *dir, unsigned int server_used,
+                     unsigned int current_ep, struct timeval *now)
+ {
+@@ -673,7 +658,7 @@ nis_server_cache_add (const_nis_name nam
+   new = calloc (1, sizeof (*new) + strlen (name) + 8 + size);
+   if (new == NULL)
+     return;
+-  new->search_parent_first = search_parent_first;
++  new->search_parent = search_parent;
+   new->uses = 1;
+   new->expires = now->tv_sec + dir->do_ttl;
+   new->size = size;
+@@ -714,7 +699,7 @@ nis_server_cache_add (const_nis_name nam
+ }
+ nis_error
+-__nisfind_server (const_nis_name name, int search_parent_first,
++__nisfind_server (const_nis_name name, int search_parent,
+                 directory_obj **dir, dir_binding *dbp, unsigned int flags)
+ {
+   nis_error result = NIS_SUCCESS;
+@@ -733,7 +718,7 @@ __nisfind_server (const_nis_name name, i
+   (void) gettimeofday (&now, NULL);
+   if ((flags & NO_CACHE) == 0)
+-    *dir = nis_server_cache_search (name, search_parent_first, &server_used,
++    *dir = nis_server_cache_search (name, search_parent, &server_used,
+                                   &current_ep, &now);
+   if (*dir != NULL)
+     {
+@@ -763,10 +748,13 @@ __nisfind_server (const_nis_name name, i
+     return NIS_UNAVAIL;
+   /* Try at first, if servers in "dir" know our object */
+-  obj = first_shoot (name, search_parent_first, *dir);
++  const char *search_name = name;
++  if (search_parent)
++    search_name = __nis_domain_of (name);
++  obj = first_shoot (search_name, *dir);
+   if (obj == NULL)
+     {
+-      obj = rec_dirsearch (name, *dir, &status);
++      obj = rec_dirsearch (search_name, *dir, &status);
+       if (obj == NULL)
+       result = status;
+     }
+@@ -787,7 +775,7 @@ __nisfind_server (const_nis_name name, i
+             current_ep = dbp->current_ep;
+           }
+         if ((flags & NO_CACHE) == 0)
+-          nis_server_cache_add (name, search_parent_first, obj,
++          nis_server_cache_add (name, search_parent, obj,
+                                 server_used, current_ep, &now);
+       }
+       else
+--- libc/include/rpcsvc/nislib.h.jj    2004-10-24 16:25:25.000000000 -0400
++++ libc/include/rpcsvc/nislib.h       2007-04-06 11:04:51.000000000 -0400
+@@ -42,4 +42,6 @@ libnsl_hidden_proto (__nis_default_group
+ libnsl_hidden_proto (__nis_default_access)
+ libnsl_hidden_proto (nis_clone_object)
++extern const_nis_name __nis_domain_of (const_nis_name) __THROW;
++
+ #endif
diff --git a/src/patches/glibc/glibc-rh237711.patch b/src/patches/glibc/glibc-rh237711.patch
new file mode 100644 (file)
index 0000000..d2538d7
--- /dev/null
@@ -0,0 +1,69 @@
+2007-05-07  Ulrich Drepper  <drepper@redhat.com>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       * malloc/arena.c (heap_info): Add mprotect_size field, adjust pad.
+       (new_heap): Initialize mprotect_size.
+       (grow_heap): When growing, only mprotect from mprotect_size till
+       new_size if mprotect_size is smaller.  When shrinking, use PROT_NONE
+       MMAP for __libc_enable_secure only, otherwise use MADV_DONTNEED.
+
+--- libc/malloc/arena.c        27 Oct 2006 23:11:43 -0000      1.25
++++ libc/malloc/arena.c        7 May 2007 15:30:57 -0000       1.26
+@@ -57,7 +57,8 @@ typedef struct _heap_info {
+   mstate ar_ptr; /* Arena for this heap. */
+   struct _heap_info *prev; /* Previous heap. */
+   size_t size;   /* Current size in bytes. */
+-  size_t pad;    /* Make sure the following data is properly aligned. */
++  size_t mprotect_size;       /* Size in bytes that has been mprotected
++                         PROT_READ|PROT_WRITE.  */
+ } heap_info;
+ /* Thread specific data */
+@@ -654,6 +655,7 @@ new_heap(size, top_pad) size_t size, top
+   }
+   h = (heap_info *)p2;
+   h->size = size;
++  h->mprotect_size = size;
+   THREAD_STAT(stat_n_heaps++);
+   return h;
+ }
+@@ -676,17 +678,34 @@ grow_heap(h, diff) heap_info *h; long di
+     new_size = (long)h->size + diff;
+     if((unsigned long) new_size > (unsigned long) HEAP_MAX_SIZE)
+       return -1;
+-    if(mprotect((char *)h + h->size, diff, PROT_READ|PROT_WRITE) != 0)
+-      return -2;
++    if((unsigned long) new_size > h->mprotect_size) {
++      if (mprotect((char *)h + h->mprotect_size,
++                 (unsigned long) new_size - h->mprotect_size,
++                 PROT_READ|PROT_WRITE) != 0)
++      return -2;
++      h->mprotect_size = new_size;
++    }
+   } else {
+     new_size = (long)h->size + diff;
+     if(new_size < (long)sizeof(*h))
+       return -1;
+     /* Try to re-map the extra heap space freshly to save memory, and
+        make it inaccessible. */
+-    if((char *)MMAP((char *)h + new_size, -diff, PROT_NONE,
+-                    MAP_PRIVATE|MAP_FIXED) == (char *) MAP_FAILED)
+-      return -2;
++#ifdef _LIBC
++    if (__builtin_expect (__libc_enable_secure, 0))
++#else
++    if (1)
++#endif
++      {
++      if((char *)MMAP((char *)h + new_size, -diff, PROT_NONE,
++                      MAP_PRIVATE|MAP_FIXED) == (char *) MAP_FAILED)
++        return -2;
++      h->mprotect_size = new_size;
++      }
++#ifdef _LIBC
++    else
++      madvise ((char *)h + new_size, -diff, MADV_DONTNEED);
++#endif
+     /*fprintf(stderr, "shrink %p %08lx\n", h, new_size);*/
+   }
+   h->size = new_size;
diff --git a/src/patches/glibc/glibc-rh238431.patch b/src/patches/glibc/glibc-rh238431.patch
new file mode 100644 (file)
index 0000000..ff22dd7
--- /dev/null
@@ -0,0 +1,41 @@
+2007-04-30  Jakub Jelinek  <jakub@redhat.com>
+
+       * stdio-common/printf_fp.c (___printf_fp): Don't print negative sign
+       for exponent 0.
+       * stdio-common/tfformat.c (sprint_doubles): Add a new test.
+
+--- libc/stdio-common/printf_fp.c      16 Apr 2007 23:28:26 -0000      1.62
++++ libc/stdio-common/printf_fp.c      30 Apr 2007 22:31:21 -0000      1.63
+@@ -793,7 +793,7 @@ ___printf_fp (FILE *fp,
+   else
+     {
+       /* This is a special case.  We don't need a factor because the
+-       numbers are in the range of 0.0 <= fp < 8.0.  We simply
++       numbers are in the range of 1.0 <= |fp| < 8.0.  We simply
+        shift it to the right place and divide it by 1.0 to get the
+        leading digit.  (Of course this division is not really made.)  */
+       assert (0 <= exponent && exponent < 3 &&
+@@ -1013,6 +1013,12 @@ ___printf_fp (FILE *fp,
+                 {
+                   *wstartp = '1';
+                   exponent += expsign == 0 ? 1 : -1;
++
++                  /* The above exponent adjustment could lead to 1.0e-00,
++                     e.g. for 0.999999999.  Make sure exponent 0 always
++                     uses + sign.  */
++                  if (exponent == 0)
++                    expsign = 0;
+                 }
+               else if (intdig_no == dig_max)
+                 {
+--- libc/stdio-common/tfformat.c       16 Apr 2007 23:28:37 -0000      1.9
++++ libc/stdio-common/tfformat.c       30 Apr 2007 22:31:36 -0000      1.10
+@@ -4021,6 +4021,8 @@ sprint_double_type sprint_doubles[] =
+   {__LINE__, 0.000098,                        "0.0001", "%#.0g"},
+   {__LINE__, 0.0000996,                       "0.00010", "%#.2g"},
+   {__LINE__, 9.999999999999999e-05,   "0.0001", "%g"},
++  {__LINE__, 1.0,                     "1.000000e+00", "%e"},
++  {__LINE__, .9999999999999999,               "1.000000e+00", "%e"},
+   {0 }
diff --git a/src/patches/glibc/glibc-rh247788.patch b/src/patches/glibc/glibc-rh247788.patch
new file mode 100644 (file)
index 0000000..1d72657
--- /dev/null
@@ -0,0 +1,133 @@
+2007-08-02  Jakub Jelinek  <jakub@redhat.com>
+
+       * intl/dcigettext.c (_nl_find_msg): Return (char *) -1 if
+       domain->conv is (__gconv_t) -2.
+       * intl/loadmsgcat.c (_nl_init_domain_conv): If __gconv_open
+       returns non-__GCONV_OK and non-__GCONV_NULCONV, set
+       domain->conv to (__gconv_t) -2.
+       (_nl_free_domain_conv): Don't call __gconv_close on
+       (__gconv_t) -2.
+
+2007-07-19  Jakub Jelinek  <jakub@redhat.com>
+
+       * iconv/gconv_int.h (__GCONV_NULCONV): New internal only error code.
+       * iconv/gconv_cache.c (__gconv_lookup_cache): Return __GCONV_NULCONV
+       if from and to charsets are the same.
+       * iconv/gconv_db.c (__gconv_find_transform): Likewise.
+
+2007-07-11  Jakub Jelinek  <jakub@redhat.com>
+
+       * intl/finddomain.c (_nl_find_domain): If _nl_explode_name
+       returned -1, return NULL.
+       * intl/explodename.c (_nl_explode_name): Return -1 if
+       _nl_normalize_codeset failed.
+
+--- libc/intl/dcigettext.c.jj  2007-08-02 10:33:21.000000000 -0400
++++ libc/intl/dcigettext.c     2007-08-02 15:03:56.000000000 -0400
+@@ -818,6 +818,13 @@ _nl_find_msg (domain_file, domainbinding
+ # endif
+       )
+     {
++# ifdef _LIBC
++      if (__builtin_expect (domain->conv == (__gconv_t) -2, 0))
++      /* Nothing we can do, no more memory.  We cannot use the
++         translation because it might be encoded incorrectly.  */
++      return (char *) -1;
++# endif
++
+       /* We are supposed to do a conversion.  First allocate an
+        appropriate table with the same structure as the table
+        of translations in the file, where we can put the pointers
+--- libc/iconv/gconv_cache.c.jj        2007-08-02 10:33:20.000000000 -0400
++++ libc/iconv/gconv_cache.c   2007-08-02 10:48:35.000000000 -0400
+@@ -274,7 +274,7 @@ __gconv_lookup_cache (const char *toset,
+   /* Avoid copy-only transformations if the user requests.   */
+   if (__builtin_expect (flags & GCONV_AVOID_NOCONV, 0) && fromidx == toidx)
+-    return __GCONV_NOCONV;
++    return __GCONV_NULCONV;
+   /* If there are special conversions available examine them first.  */
+   if (fromidx != 0 && toidx != 0
+--- libc/iconv/gconv_db.c.jj   2004-08-06 13:50:31.000000000 -0400
++++ libc/iconv/gconv_db.c      2007-08-02 10:48:35.000000000 -0400
+@@ -717,7 +717,7 @@ __gconv_find_transform (const char *tose
+     {
+       /* Both character sets are the same.  */
+       __libc_lock_unlock (__gconv_lock);
+-      return __GCONV_NOCONV;
++      return __GCONV_NULCONV;
+     }
+   result = find_derivation (toset, toset_expand, fromset, fromset_expand,
+--- libc/iconv/gconv_int.h.jj  2004-03-24 22:51:56.000000000 -0500
++++ libc/iconv/gconv_int.h     2007-08-02 10:48:35.000000000 -0400
+@@ -112,6 +112,12 @@ enum
+   GCONV_AVOID_NOCONV = 1 << 0
+ };
++/* When GCONV_AVOID_NOCONV is set and no conversion is needed,
++   __GCONV_NULCONV should be returned.  */
++enum
++{
++  __GCONV_NULCONV = -1
++};
+ /* Global variables.  */
+--- libc/intl/explodename.c.jj 2003-01-08 01:34:43.000000000 -0500
++++ libc/intl/explodename.c    2007-08-02 10:48:35.000000000 -0400
+@@ -108,7 +108,9 @@ _nl_explode_name (name, language, modifi
+           {
+             *normalized_codeset = _nl_normalize_codeset (*codeset,
+                                                          cp - *codeset);
+-            if (strcmp (*codeset, *normalized_codeset) == 0)
++            if (*normalized_codeset == NULL)
++              return -1;
++            else if (strcmp (*codeset, *normalized_codeset) == 0)
+               free ((char *) *normalized_codeset);
+             else
+               mask |= XPG_NORM_CODESET;
+--- libc/intl/finddomain.c.jj  2007-08-02 10:33:20.000000000 -0400
++++ libc/intl/finddomain.c     2007-08-02 10:48:35.000000000 -0400
+@@ -126,6 +126,9 @@ _nl_find_domain (dirname, locale, domain
+      we use XPG4 style, and `_', `+', and `,' if we use CEN syntax.  */
+   mask = _nl_explode_name (locale, &language, &modifier, &territory,
+                          &codeset, &normalized_codeset);
++  if (mask == -1)
++    /* This means we are out of core.  */
++    return NULL;
+   /* We need to protect modifying the _NL_LOADED_DOMAINS data.  */
+   __libc_rwlock_wrlock (lock);
+--- libc/intl/loadmsgcat.c.jj  2004-09-26 01:06:56.000000000 -0400
++++ libc/intl/loadmsgcat.c     2007-08-02 15:03:21.000000000 -0400
+@@ -834,10 +834,15 @@ _nl_init_domain_conv (domain_file, domai
+         /* We always want to use transliteration.  */
+         outcharset = norm_add_slashes (outcharset, "TRANSLIT");
+         charset = norm_add_slashes (charset, "");
+-        if (__gconv_open (outcharset, charset, &domain->conv,
+-                          GCONV_AVOID_NOCONV)
+-            != __GCONV_OK)
+-          domain->conv = (__gconv_t) -1;
++        int res = __gconv_open (outcharset, charset, &domain->conv,
++                                GCONV_AVOID_NOCONV);
++        if (res != __GCONV_OK)
++          {
++            if (res == __GCONV_NULCONV)
++              domain->conv = (__gconv_t) -1;
++            else
++              domain->conv = (__gconv_t) -2;
++          }
+ # else
+ #  if HAVE_ICONV
+         /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
+@@ -882,7 +887,7 @@ _nl_free_domain_conv (domain)
+     free (domain->conv_tab);
+ #ifdef _LIBC
+-  if (domain->conv != (__gconv_t) -1)
++  if (domain->conv != (__gconv_t) -1 && domain->conv != (__gconv_t) -2)
+     __gconv_close (domain->conv);
+ #else
+ # if HAVE_ICONV
diff --git a/src/patches/glibc/glibc-rh248281.patch b/src/patches/glibc/glibc-rh248281.patch
new file mode 100644 (file)
index 0000000..55eea12
--- /dev/null
@@ -0,0 +1,132 @@
+2007-07-16  Jakub Jelinek  <jakub@redhat.com>
+
+       * libio/iopopen.c (_IO_new_proc_open): Don't close child_std_end
+       if one of proc_file_chain streams has that fileno.
+       * stdio-common/Makefile (tests): Add tst-popen2.
+       * stdio-common/tst-popen2.c: New test.
+
+--- libc/libio/iopopen.c       14 Sep 2004 04:24:45 -0000      1.33
++++ libc/libio/iopopen.c       19 Jul 2007 17:02:07 -0000      1.34
+@@ -169,7 +170,15 @@ _IO_new_proc_open (fp, command, mode)
+          popen() calls that remain open in the parent process are closed
+        in the new child process." */
+       for (p = proc_file_chain; p; p = p->next)
+-      _IO_close (_IO_fileno ((_IO_FILE *) p));
++      {
++        int fd = _IO_fileno ((_IO_FILE *) p);
++
++        /* If any stream from previous popen() calls has fileno
++           child_std_end, it has been already closed by the dup2 syscall
++           above.  */
++        if (fd != child_std_end)
++          _IO_close (fd);
++      }
+       _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
+       _IO__exit (127);
+--- libc/stdio-common/Makefile 8 Jul 2007 04:41:08 -0000       1.104
++++ libc/stdio-common/Makefile 19 Jul 2007 17:02:55 -0000      1.105
+@@ -54,7 +54,7 @@ tests := tstscanf test_rdwr test-popen t
+        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 bug17 bug18 bug18a bug19 bug19a
++       tst-fwrite bug16 bug17 bug18 bug18a bug19 bug19a tst-popen2
+ test-srcs = tst-unbputc tst-printf
+--- libc/stdio-common/tst-popen2.c     1 Jan 1970 00:00:00 -0000
++++ libc/stdio-common/tst-popen2.c     19 Jul 2007 17:02:43 -0000      1.1
+@@ -0,0 +1,92 @@
++#include <stdio.h>
++#include <string.h>
++#include <unistd.h>
++
++static int
++do_test (void)
++{
++  int fd = dup (fileno (stdout));
++  if (fd <= 1)
++    {
++      puts ("dup failed");
++      return 1;
++    }
++
++  FILE *f1 = fdopen (fd, "w");
++  if (f1 == NULL)
++    {
++      printf ("fdopen failed: %m\n");
++      return 1;
++    }
++
++  fclose (stdout);
++
++  FILE *f2 = popen ("echo test1", "r");
++  if (f2 == NULL)
++    {
++      fprintf (f1, "1st popen failed: %m\n");
++      return 1;
++    }
++  FILE *f3 = popen ("echo test2", "r");
++  if (f2 == NULL || f3 == NULL)
++    {
++      fprintf (f1, "2nd popen failed: %m\n");
++      return 1;
++    }
++
++  char *line = NULL;
++  size_t len = 0;
++  int result = 0;
++  if (getline (&line, &len, f2) != 6)
++    {
++      fputs ("could not read line from 1st popen\n", f1);
++      result = 1;
++    }
++  else if (strcmp (line, "test1\n") != 0)
++    {
++      fprintf (f1, "read \"%s\"\n", line);
++      result = 1;
++    }
++
++  if (getline (&line, &len, f2) != -1)
++    {
++      fputs ("second getline did not return -1\n", f1);
++      result = 1;
++    }
++
++  if (getline (&line, &len, f3) != 6)
++    {
++      fputs ("could not read line from 2nd popen\n", f1);
++      result = 1;
++    }
++  else if (strcmp (line, "test2\n") != 0)
++    {
++      fprintf (f1, "read \"%s\"\n", line);
++      result = 1;
++    }
++
++  if (getline (&line, &len, f3) != -1)
++    {
++      fputs ("second getline did not return -1\n", f1);
++      result = 1;
++    }
++
++  int ret = pclose (f2);
++  if (ret != 0)
++    {
++      fprintf (f1, "1st pclose returned %d\n", ret);
++      result = 1;
++    }
++
++  ret = pclose (f3);
++  if (ret != 0)
++    {
++      fprintf (f1, "2nd pclose returned %d\n", ret);
++      result = 1;
++    }
++
++  return result;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-rh254115.patch b/src/patches/glibc/glibc-rh254115.patch
new file mode 100644 (file)
index 0000000..3449462
--- /dev/null
@@ -0,0 +1,35 @@
+2007-08-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * nis/nis_table.c (nis_list): Don't fail if __follow_path returned
+       NIS_NOTFOUND.
+
+--- libc/nis/nis_table.c       21 Mar 2007 20:24:59 -0000      1.41
++++ libc/nis/nis_table.c       22 Aug 2007 16:04:09 -0000      1.42
+@@ -372,7 +372,8 @@ nis_list (const_nis_name name, unsigned 
+                                            &bptr);
+               if (clnt_status != NIS_SUCCESS)
+                 {
+-                  NIS_RES_STATUS (res) = clnt_status;
++                  if (clnt_status == NIS_NOMEMORY)
++                    NIS_RES_STATUS (res) = clnt_status;
+                   ++done;
+                 }
+               else
+@@ -452,10 +453,14 @@ nis_list (const_nis_name name, unsigned 
+                 ++done;
+               else
+                 {
+-                  NIS_RES_STATUS (res)
++                  clnt_status
+                     = __follow_path (&tablepath, &tableptr, ibreq, &bptr);
+-                  if (NIS_RES_STATUS (res) != NIS_SUCCESS)
+-                    ++done;
++                  if (clnt_status != NIS_SUCCESS)
++                    {
++                      if (clnt_status == NIS_NOMEMORY)
++                        NIS_RES_STATUS (res) = clnt_status;
++                      ++done;
++                    }
+                 }
+             }
+           break;
diff --git a/src/patches/glibc/glibc-rh339821.patch b/src/patches/glibc/glibc-rh339821.patch
new file mode 100644 (file)
index 0000000..9733f2a
--- /dev/null
@@ -0,0 +1,17 @@
+2007-10-18  Ulrich Drepper  <drepper@redhat.com>
+
+       * sunrpc/clnt_udp.c (clntudp_call): Don't block in recvfrom call
+       even if the poll result indicates there is data to read.
+       Patch by Jeff Moyer <jmoyer@redhat.com>.
+
+--- libc/sunrpc/clnt_udp.c     20 Dec 2005 22:38:40 -0000      1.33
++++ libc/sunrpc/clnt_udp.c     18 Oct 2007 22:23:57 -0000      1.34
+@@ -413,7 +413,7 @@ send_again:
+       {
+         fromlen = sizeof (struct sockaddr);
+         inlen = __recvfrom (cu->cu_sock, cu->cu_inbuf,
+-                            (int) cu->cu_recvsz, 0,
++                            (int) cu->cu_recvsz, MSG_DONTWAIT,
+                             (struct sockaddr *) &from, &fromlen);
+       }
+       while (inlen < 0 && errno == EINTR);
diff --git a/src/patches/glibc/glibc-rh346321.patch b/src/patches/glibc/glibc-rh346321.patch
new file mode 100644 (file)
index 0000000..8a24fa7
--- /dev/null
@@ -0,0 +1,36 @@
+2008-01-05  Jakub Jelinek  <jakub@redhat.com>
+
+       [BZ #5112]
+       * nscd/connections.c (restart): Fix condition.
+
+2007-10-05  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #5112]
+       * nscd/connections.c (restart): Don't resync if database is
+       disabled.  Patch mostly by Brian De Wolf <bldewolf@csupomona.edu>.
+
+--- libc/nscd/connections.c    29 Aug 2007 06:09:59 -0000      1.102
++++ libc/nscd/connections.c    4 Mar 2008 01:53:50 -0000       1.109
+@@ -1284,14 +1302,15 @@ cannot change to old working directory: 
+   /* Synchronize memory.  */
+   for (int cnt = 0; cnt < lastdb; ++cnt)
+-    {
+-      /* Make sure nobody keeps using the database.  */
+-      dbs[cnt].head->timestamp = 0;
++    if (dbs[cnt].enabled)
++      {
++      /* Make sure nobody keeps using the database.  */
++      dbs[cnt].head->timestamp = 0;
+-      if (dbs[cnt].persistent)
+-      // XXX async OK?
+-      msync (dbs[cnt].head, dbs[cnt].memsize, MS_ASYNC);
+-    }
++      if (dbs[cnt].persistent)
++        // XXX async OK?
++        msync (dbs[cnt].head, dbs[cnt].memsize, MS_ASYNC);
++      }
+   /* The preparations are done.  */
+   execv ("/proc/self/exe", argv);
diff --git a/src/patches/glibc/glibc-rh385601.patch b/src/patches/glibc/glibc-rh385601.patch
new file mode 100644 (file)
index 0000000..ee1a3dc
--- /dev/null
@@ -0,0 +1,1979 @@
+--- libc/include/ifaddrs.h.jj  2003-06-10 04:53:57.000000000 -0400
++++ libc/include/ifaddrs.h     2007-12-14 22:52:11.000000000 -0500
+@@ -1,10 +1,28 @@
+ #ifndef _IFADDRS_H
+ #include <inet/ifaddrs.h>
+ #include <stdbool.h>
++#include <stdint.h>
+ libc_hidden_proto (getifaddrs)
+ libc_hidden_proto (freeifaddrs)
+-extern void __check_pf (bool *seen_ipv4, bool *seen_ipv6) attribute_hidden;
++struct in6addrinfo
++{
++  enum {
++    in6ai_deprecated = 1,
++    in6ai_homeaddress = 2
++  } flags:8;
++  uint8_t prefixlen;
++  uint16_t :16;
++  uint32_t index;
++  uint32_t addr[4];
++};
++
++extern void __check_pf (bool *seen_ipv4, bool *seen_ipv6,
++                      struct in6addrinfo **in6ai, size_t *in6ailen)
++  attribute_hidden;
++extern void __check_native (uint32_t a1_index, int *a1_native,
++                          uint32_t a2_index, int *a2_native)
++  attribute_hidden;
+ #endif        /* ifaddrs.h */
+--- libc/nscd/gai.c.jj 2007-12-14 22:52:09.000000000 -0500
++++ libc/nscd/gai.c    2007-12-14 22:52:11.000000000 -0500
+@@ -9,6 +9,7 @@
+ #define __bind bind
+ #define __sendto sendto
+ #define __strchrnul strchrnul
++#define __getline getline
+ /* nscd uses 1MB or 2MB thread stacks.  */
+ #define __libc_use_alloca(size) (size <= __MAX_ALLOCA_CUTOFF)
+@@ -16,6 +17,7 @@
+ /* Support code.  */
+ #include <check_pf.c>
++#include <check_native.c>
+ #ifdef HAVE_LIBIDN
+ # include <libidn/idn-stub.c>
+ #endif
+--- libc/sysdeps/unix/sysv/linux/check_pf.c.jj 2007-12-14 22:52:09.000000000 -0500
++++ libc/sysdeps/unix/sysv/linux/check_pf.c    2007-12-14 22:53:48.000000000 -0500
+@@ -1,5 +1,5 @@
+ /* Determine protocol families for which interfaces exist.  Linux version.
+-   Copyright (C) 2003 Free Software Foundation, Inc.
++   Copyright (C) 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
+@@ -17,10 +17,12 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+-#include <alloca.h>
++#include <assert.h>
+ #include <errno.h>
+ #include <ifaddrs.h>
+ #include <netdb.h>
++#include <stddef.h>
++#include <stdlib.h>
+ #include <string.h>
+ #include <time.h>
+ #include <unistd.h>
+@@ -30,16 +32,30 @@
+ #include <linux/netlink.h>
+ #include <linux/rtnetlink.h>
+-#include "kernel-features.h"
++#include <not-cancel.h>
++#include <kernel-features.h>
++
++
++#ifndef IFA_F_HOMEADDRESS
++# define IFA_F_HOMEADDRESS 0
++#endif
++#ifndef IFA_F_OPTIMISTIC
++# define IFA_F_OPTIMISTIC 0
++#endif
+ static int
+-make_request (int fd, pid_t pid, bool *seen_ipv4, bool *seen_ipv6)
++make_request (int fd, pid_t pid, bool *seen_ipv4, bool *seen_ipv6,
++            struct in6addrinfo **in6ai, size_t *in6ailen)
+ {
+-  struct
++  struct req
+   {
+     struct nlmsghdr nlh;
+     struct rtgenmsg g;
++    /* struct rtgenmsg consists of a single byte.  This means there
++       are three bytes of padding included in the REQ definition.
++       We make them explicit here.  */
++    char pad[3];
+   } req;
+   struct sockaddr_nl nladdr;
+@@ -50,6 +66,9 @@ make_request (int fd, pid_t pid, bool *s
+   req.nlh.nlmsg_seq = time (NULL);
+   req.g.rtgen_family = AF_UNSPEC;
++  assert (sizeof (req) - offsetof (struct req, pad) == 3);
++  memset (req.pad, '\0', sizeof (req.pad));
++
+   memset (&nladdr, '\0', sizeof (nladdr));
+   nladdr.nl_family = AF_NETLINK;
+@@ -85,6 +104,12 @@ make_request (int fd, pid_t pid, bool *s
+   *seen_ipv6 = false;
+   bool done = false;
++  struct in6ailist
++  {
++    struct in6addrinfo info;
++    struct in6ailist *next;
++  } *in6ailist = NULL;
++  size_t in6ailistlen = 0;
+   do
+     {
+@@ -115,6 +140,8 @@ make_request (int fd, pid_t pid, bool *s
+         if (nlmh->nlmsg_type == RTM_NEWADDR)
+           {
+             struct ifaddrmsg *ifam = (struct ifaddrmsg *) NLMSG_DATA (nlmh);
++            struct rtattr *rta = IFA_RTA (ifam);
++            size_t len = nlmh->nlmsg_len - NLMSG_LENGTH (sizeof (*ifam));
+             switch (ifam->ifa_family)
+               {
+@@ -126,8 +153,56 @@ make_request (int fd, pid_t pid, bool *s
+                 break;
+               default:
+                 /* Ignore.  */
+-                break;
++                continue;
++              }
++
++              if (in6ai == NULL)
++                continue;
++
++            const void *local = NULL;
++            const void *address = NULL;
++            while (RTA_OK (rta, len))
++              {
++                switch (rta->rta_type)
++                  {
++                  case IFA_LOCAL:
++                    local = RTA_DATA (rta);
++                    break;
++
++                  case IFA_ADDRESS:
++                    address = RTA_DATA (rta);
++                    goto out;
++                  }
++
++                rta = RTA_NEXT (rta, len);
++              }
++
++            if (local != NULL)
++              address = local;
++          out:;
++
++            struct in6ailist *newp = alloca (sizeof (*newp));
++            newp->info.flags = (((ifam->ifa_flags
++                                  & (IFA_F_DEPRECATED
++                                     | IFA_F_OPTIMISTIC))
++                                 ? in6ai_deprecated : 0)
++                                | ((ifam->ifa_flags
++                                    & IFA_F_HOMEADDRESS)
++                                   ? in6ai_homeaddress : 0));
++            newp->info.prefixlen = ifam->ifa_prefixlen;
++            newp->info.index = ifam->ifa_index;
++            if (ifam->ifa_family == AF_INET)
++              {
++                newp->info.addr[0] = 0;
++                newp->info.addr[1] = 0;
++                newp->info.addr[2] = htonl (0xffff);
++                newp->info.addr[3] = *(const in_addr_t *) address;
+               }
++            else
++              memcpy (newp->info.addr, address, sizeof (newp->info.addr));
++            newp->next = in6ailist;
++            in6ailist = newp;
++            ++in6ailistlen;
+           }
+         else if (nlmh->nlmsg_type == NLMSG_DONE)
+           /* We found the end, leave the loop.  */
+@@ -137,7 +212,23 @@ make_request (int fd, pid_t pid, bool *s
+     }
+   while (! done);
+-  __close (fd);
++  close_not_cancel_no_status (fd);
++
++  if (*seen_ipv6 && in6ailist != NULL)
++    {
++      *in6ai = malloc (in6ailistlen * sizeof (**in6ai));
++      if (*in6ai == NULL)
++      goto out_fail;
++
++      *in6ailen = in6ailistlen;
++
++      do
++      {
++        (*in6ai)[--in6ailistlen] = in6ailist->info;
++        in6ailist = in6ailist->next;
++      }
++      while (in6ailist != NULL);
++    }
+   if (use_malloc)
+     free (buf);
+@@ -162,8 +253,15 @@ extern int __no_netlink_support attribut
+ void
+ attribute_hidden
+-__check_pf (bool *seen_ipv4, bool *seen_ipv6)
++__check_pf (bool *seen_ipv4, bool *seen_ipv6,
++          struct in6addrinfo **in6ai, size_t *in6ailen)
+ {
++  if (in6ai)
++    {
++      *in6ai = NULL;
++      *in6ailen = 0;
++    }
++
+   if (! __no_netlink_support)
+     {
+       int fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+@@ -177,7 +275,8 @@ __check_pf (bool *seen_ipv4, bool *seen_
+       if (fd >= 0
+         && __bind (fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) == 0
+         && __getsockname (fd, (struct sockaddr *) &nladdr, &addr_len) == 0
+-        && make_request (fd, nladdr.nl_pid, seen_ipv4, seen_ipv6) == 0)
++        && make_request (fd, nladdr.nl_pid, seen_ipv4, seen_ipv6,
++                         in6ai, in6ailen) == 0)
+       /* It worked.  */
+       return;
+--- libc/sysdeps/unix/sysv/linux/check_native.c.jj     2007-11-13 10:14:11.610303087 -0500
++++ libc/sysdeps/unix/sysv/linux/check_native.c        2007-12-14 22:52:11.000000000 -0500
+@@ -0,0 +1,172 @@
++/* Determine whether interfaces use native transport.  Linux version.
++   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 <assert.h>
++#include <errno.h>
++#include <ifaddrs.h>
++#include <stddef.h>
++#include <stdint.h>
++#include <stdlib.h>
++#include <time.h>
++#include <unistd.h>
++#include <net/if.h>
++#include <net/if_arp.h>
++#include <sys/ioctl.h>
++
++#include <asm/types.h>
++#include <linux/netlink.h>
++#include <linux/rtnetlink.h>
++
++#include <not-cancel.h>
++
++
++void
++__check_native (uint32_t a1_index, int *a1_native,
++              uint32_t a2_index, int *a2_native)
++{
++  int fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
++
++  struct sockaddr_nl nladdr;
++  memset (&nladdr, '\0', sizeof (nladdr));
++  nladdr.nl_family = AF_NETLINK;
++
++  socklen_t addr_len = sizeof (nladdr);
++
++  if (fd < 0
++      || __bind (fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) != 0
++      || __getsockname (fd, (struct sockaddr *) &nladdr, &addr_len) != 0)
++    return;
++
++  pid_t pid = nladdr.nl_pid;
++  struct req
++  {
++    struct nlmsghdr nlh;
++    struct rtgenmsg g;
++    /* struct rtgenmsg consists of a single byte.  This means there
++       are three bytes of padding included in the REQ definition.
++       We make them explicit here.  */
++    char pad[3];
++  } req;
++
++  req.nlh.nlmsg_len = sizeof (req);
++  req.nlh.nlmsg_type = RTM_GETLINK;
++  req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
++  req.nlh.nlmsg_pid = 0;
++  req.nlh.nlmsg_seq = time (NULL);
++  req.g.rtgen_family = AF_UNSPEC;
++
++  assert (sizeof (req) - offsetof (struct req, pad) == 3);
++  memset (req.pad, '\0', sizeof (req.pad));
++
++  memset (&nladdr, '\0', sizeof (nladdr));
++  nladdr.nl_family = AF_NETLINK;
++
++#ifdef PAGE_SIZE
++  /* Help the compiler optimize out the malloc call if PAGE_SIZE
++     is constant and smaller or equal to PTHREAD_STACK_MIN/4.  */
++  const size_t buf_size = PAGE_SIZE;
++#else
++  const size_t buf_size = __getpagesize ();
++#endif
++  bool use_malloc = false;
++  char *buf;
++
++  if (__libc_use_alloca (buf_size))
++    buf = alloca (buf_size);
++  else
++    {
++      buf = malloc (buf_size);
++      if (buf != NULL)
++      use_malloc = true;
++      else
++      goto out_fail;
++    }
++
++  struct iovec iov = { buf, buf_size };
++
++  if (TEMP_FAILURE_RETRY (__sendto (fd, (void *) &req, sizeof (req), 0,
++                                  (struct sockaddr *) &nladdr,
++                                  sizeof (nladdr))) < 0)
++    goto out_fail;
++
++  bool done = false;
++  do
++    {
++      struct msghdr msg =
++      {
++        (void *) &nladdr, sizeof (nladdr),
++        &iov, 1,
++        NULL, 0,
++        0
++      };
++
++      ssize_t read_len = TEMP_FAILURE_RETRY (__recvmsg (fd, &msg, 0));
++      if (read_len < 0)
++      goto out_fail;
++
++      if (msg.msg_flags & MSG_TRUNC)
++      goto out_fail;
++
++      struct nlmsghdr *nlmh;
++      for (nlmh = (struct nlmsghdr *) buf;
++         NLMSG_OK (nlmh, (size_t) read_len);
++         nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, read_len))
++      {
++        if (nladdr.nl_pid != 0 || (pid_t) nlmh->nlmsg_pid != pid
++            || nlmh->nlmsg_seq != req.nlh.nlmsg_seq)
++          continue;
++
++        if (nlmh->nlmsg_type == RTM_NEWLINK)
++          {
++            struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlmh);
++            int native = (ifim->ifi_type != ARPHRD_TUNNEL6
++                          && ifim->ifi_type != ARPHRD_TUNNEL
++                          && ifim->ifi_type != ARPHRD_SIT);
++
++            if (a1_index == ifim->ifi_index)
++              {
++                *a1_native = native;
++                a1_index = 0xffffffffu;
++              }
++            if (a2_index == ifim->ifi_index)
++              {
++                *a2_native = native;
++                a2_index = 0xffffffffu;
++              }
++
++            if (a1_index == 0xffffffffu
++                && a2_index == 0xffffffffu)
++              goto out;
++          }
++        else if (nlmh->nlmsg_type == NLMSG_DONE)
++          /* We found the end, leave the loop.  */
++          done = true;
++      }
++    }
++  while (! done);
++
++ out:
++  close_not_cancel_no_status (fd);
++
++  return;
++
++out_fail:
++  if (use_malloc)
++    free (buf);
++}
+--- libc/sysdeps/posix/getaddrinfo.c.jj        2007-12-14 22:52:09.000000000 -0500
++++ libc/sysdeps/posix/getaddrinfo.c   2007-12-14 22:52:11.000000000 -0500
+@@ -56,6 +56,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBI
+ #include <not-cancel.h>
+ #include <nscd/nscd-client.h>
+ #include <nscd/nscd_proto.h>
++#include <sys/stat.h>
++#include <bits/libc-lock.h>
++#include <stdio_ext.h>
++#include <ctype.h>
+ #ifdef HAVE_LIBIDN
+ extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
+@@ -1138,6 +1142,62 @@ struct sort_result
+ };
++struct sort_result_new
++{
++  struct addrinfo *dest_addr;
++  struct sockaddr_storage source_addr;
++  uint8_t source_addr_len;
++  bool got_source_addr;
++  uint8_t source_addr_flags;
++  uint8_t prefixlen;
++  uint32_t index;
++  int32_t native;
++};
++
++struct sort_result_combo
++{
++  struct sort_result_new *results;
++  int nresults;
++};
++
++struct sort_order
++{
++  size_t index;
++  struct sort_result_combo *src;
++};
++
++#if __BYTE_ORDER == __BIG_ENDIAN
++# define htonl_c(n) n
++#else
++# define htonl_c(n) __bswap_constant_32 (n)
++#endif
++
++static const struct scopeentry
++{
++  union
++  {
++    char addr[4];
++    uint32_t addr32;
++  };
++  uint32_t netmask;
++  int32_t scope;
++} default_scopes[] =
++  {
++    /* Link-local addresses: scope 2.  */
++    { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
++    { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
++    /* Site-local addresses: scope 5.  */
++    { { { 10, 0, 0, 0 } }, htonl_c (0xff000000), 5 },
++    { { { 172, 16, 0, 0 } }, htonl_c (0xfff00000), 5 },
++    { { { 192, 168, 0, 0 } }, htonl_c (0xffff0000), 5 },
++    /* Default: scope 14.  */
++    { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
++  };
++
++/* The label table.  */
++static const struct scopeentry *scopes;
++
++
+ static int
+ get_scope (const struct sockaddr_storage *ss)
+ {
+@@ -1162,17 +1222,17 @@ get_scope (const struct sockaddr_storage
+   else if (ss->ss_family == PF_INET)
+     {
+       const struct sockaddr_in *in = (const struct sockaddr_in *) ss;
+-      const uint8_t *addr = (const uint8_t *) &in->sin_addr;
+-      /* RFC 3484 specifies how to map IPv6 addresses to scopes.
+-       169.254/16 and 127/8 are link-local.  */
+-      if ((addr[0] == 169 && addr[1] == 254) || addr[0] == 127)
+-      scope = 2;
+-      else if (addr[0] == 10 || (addr[0] == 172 && addr[1] == 16)
+-             || (addr[0] == 192 && addr[1] == 168))
+-      scope = 5;
+-      else
+-      scope = 14;
++      size_t cnt = 0;
++      while (1)
++      {
++        if ((in->sin_addr.s_addr & scopes[cnt].netmask)
++            == scopes[cnt].addr32)
++          return scopes[cnt].scope;
++
++        ++cnt;
++      }
++      /* NOTREACHED */
+     }
+   else
+     /* XXX What is a good default?  */
+@@ -1269,8 +1329,8 @@ match_prefix (const struct sockaddr_stor
+   for (idx = 0; ; ++idx)
+     {
+       unsigned int bits = list[idx].bits;
+-      uint8_t *mask = list[idx].prefix.s6_addr;
+-      uint8_t *val = in6->sin6_addr.s6_addr;
++      const uint8_t *mask = list[idx].prefix.s6_addr;
++      const uint8_t *val = in6->sin6_addr.s6_addr;
+       while (bits >= 8)
+       {
+@@ -1474,6 +1534,836 @@ rfc3484_sort (const void *p1, const void
+   return 0;
+ }
++/* The label table.  */
++static const struct prefixlist *labels;
++
++/* Default labels.  */
++static const struct prefixlist default_labels_new[] =
++  {
++    /* See RFC 3484 for the details.  */
++    { { .in6_u
++      = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
++      128, 0 },
++    { { .in6_u
++      = { .u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
++      16, 2 },
++    { { .in6_u
++      = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
++      96, 3 },
++    { { .in6_u
++      = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                        0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } },
++      96, 4 },
++    /* The next two entries differ from RFC 3484.  We need to treat
++       IPv6 site-local addresses special because they are never NATed,
++       unlike site-locale IPv4 addresses.  If this would not happen, on
++       machines which have only IPv4 and IPv6 site-local addresses, the
++       sorting would prefer the IPv6 site-local addresses, causing
++       unnecessary delays when trying to connect to a global IPv6 address
++       through a site-local IPv6 address.  */
++    { { .in6_u
++      = { .u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
++      10, 5 },
++    { { .in6_u
++      = { .u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
++      7, 6 },
++    /* Additional rule for Teredo tunnels.  */
++    { { .in6_u
++      = { .u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
++      32, 7 },
++    { { .in6_u
++      = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
++      0, 1 }
++  };
++
++
++/* The precedence table.  */
++static const struct prefixlist *precedence;
++
++/* The default precedences.  */
++static const struct prefixlist default_precedence_new[] =
++  {
++    /* See RFC 3484 for the details.  */
++    { { .in6_u
++      = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
++      128, 50 },
++    { { .in6_u
++      = { .u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
++      16, 30 },
++    { { .in6_u
++      = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
++      96, 20 },
++    { { .in6_u
++      = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                        0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } },
++      96, 10 },
++    { { .in6_u
++      = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
++      0, 40 }
++  };
++
++
++static int
++get_label_new (const struct sockaddr_storage *ss)
++{
++  /* XXX What is a good default value?  */
++  return match_prefix (ss, labels, INT_MAX);
++}
++
++
++static int
++get_precedence_new (const struct sockaddr_storage *ss)
++{
++  /* XXX What is a good default value?  */
++  return match_prefix (ss, precedence, 0);
++}
++
++
++static int
++rfc3484_new_sort (const void *p1, const void *p2)
++{
++  const size_t idx1 = ((const struct sort_order *) p1)->index;
++  const size_t idx2 = ((const struct sort_order *) p2)->index;
++  struct sort_result_combo *src = ((const struct sort_order *) p1)->src;
++  struct sort_result_new *a1 = &src->results[idx1];
++  struct sort_result_new *a2 = &src->results[idx2];
++
++  /* Rule 1: Avoid unusable destinations.
++     We have the got_source_addr flag set if the destination is reachable.  */
++  if (a1->got_source_addr && ! a2->got_source_addr)
++    return -1;
++  if (! a1->got_source_addr && a2->got_source_addr)
++    return 1;
++
++
++  /* Rule 2: Prefer matching scope.  Only interesting if both
++     destination addresses are IPv6.  */
++  int a1_dst_scope
++    = get_scope ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
++
++  int a2_dst_scope
++    = get_scope ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
++
++  if (a1->got_source_addr)
++    {
++      int a1_src_scope = get_scope (&a1->source_addr);
++      int a2_src_scope = get_scope (&a2->source_addr);
++
++      if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
++      return -1;
++      if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
++      return 1;
++    }
++
++
++  /* Rule 3: Avoid deprecated addresses.  */
++  if (a1->got_source_addr)
++    {
++      if (!(a1->source_addr_flags & in6ai_deprecated)
++        && (a2->source_addr_flags & in6ai_deprecated))
++      return -1;
++      if ((a1->source_addr_flags & in6ai_deprecated)
++        && !(a2->source_addr_flags & in6ai_deprecated))
++      return 1;
++    }
++
++  /* Rule 4: Prefer home addresses.  */
++  if (a1->got_source_addr)
++    {
++      if (!(a1->source_addr_flags & in6ai_homeaddress)
++        && (a2->source_addr_flags & in6ai_homeaddress))
++      return 1;
++      if ((a1->source_addr_flags & in6ai_homeaddress)
++        && !(a2->source_addr_flags & in6ai_homeaddress))
++      return -1;
++    }
++
++  /* Rule 5: Prefer matching label.  */
++  if (a1->got_source_addr)
++    {
++      int a1_dst_label
++      = get_label_new ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
++      int a1_src_label = get_label_new (&a1->source_addr);
++
++      int a2_dst_label
++      = get_label_new ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
++      int a2_src_label = get_label_new (&a2->source_addr);
++
++      if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
++      return -1;
++      if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
++      return 1;
++    }
++
++
++  /* Rule 6: Prefer higher precedence.  */
++  int a1_prec
++    = get_precedence_new ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
++  int a2_prec
++    = get_precedence_new ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
++
++  if (a1_prec > a2_prec)
++    return -1;
++  if (a1_prec < a2_prec)
++    return 1;
++
++
++  /* Rule 7: Prefer native transport.  */
++  if (a1->got_source_addr)
++    {
++      /* The same interface index means the same interface which means
++       there is no difference in transport.  This should catch many
++       (most?) cases.  */
++      if (a1->index != a2->index)
++      {
++        int a1_native = a1->native;
++        int a2_native = a2->native;
++
++        if (a1_native == -1 || a2_native == -1)
++          {
++            uint32_t a1_index;
++            if (a1_native == -1)
++              {
++                /* If we do not have the information use 'native' as
++                   the default.  */
++                a1_native = 0;
++                a1_index = a1->index;
++              }
++            else
++              a1_index = 0xffffffffu;
++
++            uint32_t a2_index;
++            if (a2_native == -1)
++              {
++                /* If we do not have the information use 'native' as
++                   the default.  */
++                a2_native = 0;
++                a2_index = a2->index;
++              }
++            else
++              a2_index = 0xffffffffu;
++
++            __check_native (a1_index, &a1_native, a2_index, &a2_native);
++
++            /* Fill in the results in all the records.  */
++            for (int i = 0; i < src->nresults; ++i)
++              if (src->results[i].index == a1_index)
++                {
++                  assert (src->results[i].native == -1
++                          || src->results[i].native == a1_native);
++                  src->results[i].native = a1_native;
++                }
++              else if (src->results[i].index == a2_index)
++                {
++                  assert (src->results[i].native == -1
++                          || src->results[i].native == a2_native);
++                  src->results[i].native = a2_native;
++                }
++          }
++
++        if (a1_native && !a2_native)
++          return -1;
++        if (!a1_native && a2_native)
++          return 1;
++      }
++    }
++
++
++  /* Rule 8: Prefer smaller scope.  */
++  if (a1_dst_scope < a2_dst_scope)
++    return -1;
++  if (a1_dst_scope > a2_dst_scope)
++    return 1;
++
++
++  /* Rule 9: Use longest matching prefix.  */
++  if (a1->got_source_addr
++      && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
++    {
++      int bit1 = 0;
++      int bit2 = 0;
++
++      if (a1->dest_addr->ai_family == PF_INET)
++      {
++        assert (a1->source_addr.ss_family == PF_INET);
++        assert (a2->source_addr.ss_family == PF_INET);
++
++        /* Outside of subnets, as defined by the network masks,
++           common address prefixes for IPv4 addresses make no sense.
++           So, define a non-zero value only if source and
++           destination address are on the same subnet.  */
++        struct sockaddr_in *in1_dst
++          = (struct sockaddr_in *) a1->dest_addr->ai_addr;
++        in_addr_t in1_dst_addr = ntohl (in1_dst->sin_addr.s_addr);
++        struct sockaddr_in *in1_src
++          = (struct sockaddr_in *) &a1->source_addr;
++        in_addr_t in1_src_addr = ntohl (in1_src->sin_addr.s_addr);
++        in_addr_t netmask1 = 0xffffffffu << (32 - a1->prefixlen);
++
++        if ((in1_src_addr & netmask1) == (in1_dst_addr & netmask1))
++          bit1 = fls (in1_dst_addr ^ in1_src_addr);
++
++        struct sockaddr_in *in2_dst
++          = (struct sockaddr_in *) a2->dest_addr->ai_addr;
++        in_addr_t in2_dst_addr = ntohl (in2_dst->sin_addr.s_addr);
++        struct sockaddr_in *in2_src
++          = (struct sockaddr_in *) &a2->source_addr;
++        in_addr_t in2_src_addr = ntohl (in2_src->sin_addr.s_addr);
++        in_addr_t netmask2 = 0xffffffffu << (32 - a2->prefixlen);
++
++        if ((in2_src_addr & netmask2) == (in2_dst_addr & netmask2))
++          bit2 = fls (in2_dst_addr ^ in2_src_addr);
++      }
++      else if (a1->dest_addr->ai_family == PF_INET6)
++      {
++        assert (a1->source_addr.ss_family == PF_INET6);
++        assert (a2->source_addr.ss_family == PF_INET6);
++
++        struct sockaddr_in6 *in1_dst;
++        struct sockaddr_in6 *in1_src;
++        struct sockaddr_in6 *in2_dst;
++        struct sockaddr_in6 *in2_src;
++
++        in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
++        in1_src = (struct sockaddr_in6 *) &a1->source_addr;
++        in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
++        in2_src = (struct sockaddr_in6 *) &a2->source_addr;
++
++        int i;
++        for (i = 0; i < 4; ++i)
++          if (in1_dst->sin6_addr.s6_addr32[i]
++              != in1_src->sin6_addr.s6_addr32[i]
++              || (in2_dst->sin6_addr.s6_addr32[i]
++                  != in2_src->sin6_addr.s6_addr32[i]))
++            break;
++
++        if (i < 4)
++          {
++            bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
++                               ^ in1_src->sin6_addr.s6_addr32[i]));
++            bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
++                               ^ in2_src->sin6_addr.s6_addr32[i]));
++          }
++      }
++
++      if (bit1 > bit2)
++      return -1;
++      if (bit1 < bit2)
++      return 1;
++    }
++
++
++  /* Rule 10: Otherwise, leave the order unchanged.  To ensure this
++     compare with the value indicating the order in which the entries
++     have been received from the services.  NB: no two entries can have
++     the same order so the test will never return zero.  */
++  return idx1 < idx2 ? -1 : 1;
++}
++
++
++static int
++in6aicmp (const void *p1, const void *p2)
++{
++  struct in6addrinfo *a1 = (struct in6addrinfo *) p1;
++  struct in6addrinfo *a2 = (struct in6addrinfo *) p2;
++
++  return memcmp (a1->addr, a2->addr, sizeof (a1->addr));
++}
++
++
++/* Name of the config file for RFC 3484 sorting (for now).  */
++#define GAICONF_FNAME "/etc/gai.conf"
++
++
++/* Non-zero if we are supposed to reload the config file automatically
++   whenever it changed.  */
++static int gaiconf_reload_flag;
++
++/* Non-zero if gaiconf_reload_flag was ever set to true.  */
++static int gaiconf_reload_flag_ever_set;
++
++/* Last modification time.  */
++static struct timespec gaiconf_mtime;
++
++
++libc_freeres_fn(fini)
++{
++  if (labels != default_labels_new)
++    {
++      const struct prefixlist *old = labels;
++      labels = default_labels_new;
++      free ((void *) old);
++    }
++
++  if (precedence != default_precedence_new)
++    {
++      const struct prefixlist *old = precedence;
++      precedence = default_precedence_new;
++      free ((void *) old);
++    }
++
++  if (scopes != default_scopes)
++    {
++      const struct scopeentry *old = scopes;
++      scopes = default_scopes;
++      free ((void *) old);
++    }
++}
++
++
++struct prefixlist_new
++{
++  struct prefixlist entry;
++  struct prefixlist_new *next;
++};
++
++
++struct scopelist
++{
++  struct scopeentry entry;
++  struct scopelist *next;
++};
++
++
++static void
++free_prefixlist (struct prefixlist_new *list)
++{
++  while (list != NULL)
++    {
++      struct prefixlist_new *oldp = list;
++      list = list->next;
++      free (oldp);
++    }
++}
++
++
++static void
++free_scopelist (struct scopelist *list)
++{
++  while (list != NULL)
++    {
++      struct scopelist *oldp = list;
++      list = list->next;
++      free (oldp);
++    }
++}
++
++
++static int
++prefixcmp (const void *p1, const void *p2)
++{
++  const struct prefixlist *e1 = (const struct prefixlist *) p1;
++  const struct prefixlist *e2 = (const struct prefixlist *) p2;
++
++  if (e1->bits < e2->bits)
++    return 1;
++  if (e1->bits == e2->bits)
++    return 0;
++  return -1;
++}
++
++
++static int
++scopecmp (const void *p1, const void *p2)
++{
++  const struct scopeentry *e1 = (const struct scopeentry *) p1;
++  const struct scopeentry *e2 = (const struct scopeentry *) p2;
++
++  if (e1->netmask > e2->netmask)
++    return -1;
++  if (e1->netmask == e2->netmask)
++    return 0;
++  return 1;
++}
++
++static bool gaiconf_present;
++
++static void
++gaiconf_init (void)
++{
++  struct prefixlist_new *labellist = NULL;
++  size_t nlabellist = 0;
++  bool labellist_nullbits = false;
++  struct prefixlist_new *precedencelist = NULL;
++  size_t nprecedencelist = 0;
++  bool precedencelist_nullbits = false;
++  struct scopelist *scopelist =  NULL;
++  size_t nscopelist = 0;
++  bool scopelist_nullbits = false;
++
++  FILE *fp = fopen (GAICONF_FNAME, "rc");
++  if (fp != NULL)
++    {
++      struct stat64 st;
++      if (__fxstat64 (_STAT_VER, fileno (fp), &st) != 0)
++      {
++        fclose (fp);
++        goto no_file;
++      }
++
++      gaiconf_present = true;
++
++      char *line = NULL;
++      size_t linelen = 0;
++
++      __fsetlocking (fp, FSETLOCKING_BYCALLER);
++
++      while (!feof_unlocked (fp))
++      {
++        ssize_t n = __getline (&line, &linelen, fp);
++        if (n <= 0)
++          break;
++
++        /* Handle comments.  No escaping possible so this is easy.  */
++        char *cp = strchr (line, '#');
++        if (cp != NULL)
++          *cp = '\0';
++
++        cp = line;
++        while (isspace (*cp))
++          ++cp;
++
++        char *cmd = cp;
++        while (*cp != '\0' && !isspace (*cp))
++          ++cp;
++        size_t cmdlen = cp - cmd;
++
++        if (*cp != '\0')
++          *cp++ = '\0';
++        while (isspace (*cp))
++          ++cp;
++
++        char *val1 = cp;
++        while (*cp != '\0' && !isspace (*cp))
++          ++cp;
++        size_t val1len = cp - cmd;
++
++        /* We always need at least two values.  */
++        if (val1len == 0)
++          continue;
++
++        if (*cp != '\0')
++          *cp++ = '\0';
++        while (isspace (*cp))
++          ++cp;
++
++        char *val2 = cp;
++        while (*cp != '\0' && !isspace (*cp))
++          ++cp;
++
++        /*  Ignore the rest of the line.  */
++        *cp = '\0';
++
++        struct prefixlist_new **listp;
++        size_t *lenp;
++        bool *nullbitsp;
++        switch (cmdlen)
++          {
++          case 5:
++            if (strcmp (cmd, "label") == 0)
++              {
++                struct in6_addr prefix;
++                unsigned long int bits;
++                unsigned long int val;
++                char *endp;
++
++                listp = &labellist;
++                lenp = &nlabellist;
++                nullbitsp = &labellist_nullbits;
++
++              new_elem:
++                bits = 128;
++                __set_errno (0);
++                cp = strchr (val1, '/');
++                if (cp != NULL)
++                  *cp++ = '\0';
++                if (inet_pton (AF_INET6, val1, &prefix)
++                    && (cp == NULL
++                        || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
++                        || errno != ERANGE)
++                    && *endp == '\0'
++                    && bits <= 128
++                    && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
++                        || errno != ERANGE)
++                    && *endp == '\0'
++                    && val <= INT_MAX)
++                  {
++                    struct prefixlist_new *newp = malloc (sizeof (*newp));
++                    if (newp == NULL)
++                      {
++                        free (line);
++                        fclose (fp);
++                        goto no_file;
++                      }
++
++                    memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
++                    newp->entry.bits = bits;
++                    newp->entry.val = val;
++                    newp->next = *listp;
++                    *listp = newp;
++                    ++*lenp;
++                    *nullbitsp |= bits == 0;
++                  }
++              }
++            break;
++
++          case 6:
++            if (strcmp (cmd, "reload") == 0)
++              {
++                gaiconf_reload_flag = strcmp (val1, "yes") == 0;
++                if (gaiconf_reload_flag)
++                  gaiconf_reload_flag_ever_set = 1;
++              }
++            break;
++
++          case 7:
++            if (strcmp (cmd, "scopev4") == 0)
++              {
++                struct in6_addr prefix;
++                unsigned long int bits;
++                unsigned long int val;
++                char *endp;
++
++                bits = 32;
++                __set_errno (0);
++                cp = strchr (val1, '/');
++                if (cp != NULL)
++                  *cp++ = '\0';
++                if (inet_pton (AF_INET6, val1, &prefix))
++                  {
++                    if (IN6_IS_ADDR_V4MAPPED (&prefix)
++                        && (cp == NULL
++                            || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
++                            || errno != ERANGE)
++                        && *endp == '\0'
++                        && bits >= 96
++                        && bits <= 128
++                        && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
++                            || errno != ERANGE)
++                        && *endp == '\0'
++                        && val <= INT_MAX)
++                      {
++                        struct scopelist *newp;
++                      new_scope:
++                        newp = malloc (sizeof (*newp));
++                        if (newp == NULL)
++                          {
++                            free (line);
++                            fclose (fp);
++                            goto no_file;
++                          }
++
++                        newp->entry.netmask = htonl (bits != 96
++                                                     ? (0xffffffff
++                                                        << (128 - bits))
++                                                     : 0);
++                        newp->entry.addr32 = (prefix.s6_addr32[3]
++                                              & newp->entry.netmask);
++                        newp->entry.scope = val;
++                        newp->next = scopelist;
++                        scopelist = newp;
++                        ++nscopelist;
++                        scopelist_nullbits |= bits == 96;
++                      }
++                  }
++                else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
++                         && (cp == NULL
++                             || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
++                             || errno != ERANGE)
++                         && *endp == '\0'
++                         && bits <= 32
++                         && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
++                             || errno != ERANGE)
++                         && *endp == '\0'
++                         && val <= INT_MAX)
++                  {
++                    bits += 96;
++                    goto new_scope;
++                  }
++              }
++            break;
++
++          case 10:
++            if (strcmp (cmd, "precedence") == 0)
++              {
++                listp = &precedencelist;
++                lenp = &nprecedencelist;
++                nullbitsp = &precedencelist_nullbits;
++                goto new_elem;
++              }
++            break;
++          }
++      }
++
++      free (line);
++
++      fclose (fp);
++
++      /* Create the array for the labels.  */
++      struct prefixlist *new_labels;
++      if (nlabellist > 0)
++      {
++        if (!labellist_nullbits)
++          ++nlabellist;
++        new_labels = malloc (nlabellist * sizeof (*new_labels));
++        if (new_labels == NULL)
++          goto no_file;
++
++        int i = nlabellist;
++        if (!labellist_nullbits)
++          {
++            --i;
++            memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
++            new_labels[i].bits = 0;
++            new_labels[i].val = 1;
++          }
++
++        struct prefixlist_new *l = labellist;
++        while (i-- > 0)
++          {
++            new_labels[i] = l->entry;
++            l = l->next;
++          }
++        free_prefixlist (labellist);
++
++        /* Sort the entries so that the most specific ones are at
++           the beginning.  */
++        qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
++      }
++      else
++      new_labels = (struct prefixlist *) default_labels_new;
++
++      struct prefixlist *new_precedence;
++      if (nprecedencelist > 0)
++      {
++        if (!precedencelist_nullbits)
++          ++nprecedencelist;
++        new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
++        if (new_precedence == NULL)
++          {
++            if (new_labels != default_labels_new)
++              free (new_labels);
++            goto no_file;
++          }
++
++        int i = nprecedencelist;
++        if (!precedencelist_nullbits)
++          {
++            --i;
++            memset (&new_precedence[i].prefix, '\0',
++                    sizeof (struct in6_addr));
++            new_precedence[i].bits = 0;
++            new_precedence[i].val = 40;
++          }
++
++        struct prefixlist_new *l = precedencelist;
++        while (i-- > 0)
++          {
++            new_precedence[i] = l->entry;
++            l = l->next;
++          }
++        free_prefixlist (precedencelist);
++
++        /* Sort the entries so that the most specific ones are at
++           the beginning.  */
++        qsort (new_precedence, nprecedencelist, sizeof (*new_precedence),
++               prefixcmp);
++      }
++      else
++      new_precedence = (struct prefixlist *) default_precedence_new;
++
++      struct scopeentry *new_scopes;
++      if (nscopelist > 0)
++      {
++        if (!scopelist_nullbits)
++          ++nscopelist;
++        new_scopes = malloc (nscopelist * sizeof (*new_scopes));
++        if (new_scopes == NULL)
++          {
++            if (new_labels != default_labels_new)
++              free (new_labels);
++            if (new_precedence != default_precedence_new)
++              free (new_precedence);
++            goto no_file;
++          }
++
++        int i = nscopelist;
++        if (!scopelist_nullbits)
++          {
++            --i;
++            new_scopes[i].addr32 = 0;
++            new_scopes[i].netmask = 0;
++            new_scopes[i].scope = 14;
++          }
++
++        struct scopelist *l = scopelist;
++        while (i-- > 0)
++          {
++            new_scopes[i] = l->entry;
++            l = l->next;
++          }
++        free_scopelist (scopelist);
++
++        /* Sort the entries so that the most specific ones are at
++           the beginning.  */
++        qsort (new_scopes, nscopelist, sizeof (*new_scopes),
++               scopecmp);
++      }
++      else
++      new_scopes = (struct scopeentry *) default_scopes;
++
++      /* Now we are ready to replace the values.  */
++      const struct prefixlist *old = labels;
++      labels = new_labels;
++      if (old != default_labels_new)
++      free ((void *) old);
++
++      old = precedence;
++      precedence = new_precedence;
++      if (old != default_precedence_new)
++      free ((void *) old);
++
++      const struct scopeentry *oldscope = scopes;
++      scopes = new_scopes;
++      if (oldscope != default_scopes)
++      free ((void *) oldscope);
++
++      gaiconf_mtime = st.st_mtim;
++    }
++  else
++    {
++    no_file:
++      free_prefixlist (labellist);
++      free_prefixlist (precedencelist);
++      free_scopelist (scopelist);
++
++      /* If we previously read the file but it is gone now, free the
++       old data and use the builtin one.  Leave the reload flag
++       alone.  */
++      fini ();
++    }
++}
++
++static void
++gaiconf_reload (void)
++{
++  struct stat64 st;
++  if (__xstat64 (_STAT_VER, GAICONF_FNAME, &st) != 0
++      || memcmp (&st.st_mtim, &gaiconf_mtime, sizeof (gaiconf_mtime)) != 0)
++    gaiconf_init ();
++}
++
+ int
+ getaddrinfo (const char *name, const char *service,
+@@ -1517,7 +2407,7 @@ getaddrinfo (const char *name, const cha
+        added at any time.  */
+       bool seen_ipv4;
+       bool seen_ipv6;
+-      __check_pf (&seen_ipv4, &seen_ipv6);
++      __check_pf (&seen_ipv4, &seen_ipv6, NULL, NULL);
+       /* Now make a decision on what we return, if anything.  */
+       if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
+@@ -1600,9 +2490,16 @@ getaddrinfo (const char *name, const cha
+   if (j == 0)
+     return EAI_FAMILY;
+-  if (nresults > 1)
++  if (nresults <= 1)
++    goto do_ret;
++
++  /* Read the config file.  */
++  __libc_once_define (static, once);
++  __libc_once (once, gaiconf_init);
++
++  if (!gaiconf_present)
+     {
+-      /* Sort results according to RFC 3484.  */
++      /* Sort results according to RFC 3484, RHEL4 algorithm.  */
+       struct sort_result results[nresults];
+       struct addrinfo *q;
+       struct addrinfo *last = NULL;
+@@ -1671,7 +2568,196 @@ getaddrinfo (const char *name, const cha
+       /* Fill in the canonical name into the new first entry.  */
+       p->ai_canonname = canonname;
+     }
++  else
++    {
++      /* Sort results according to RFC 3484, Fedora 9 algorithm.  */
++      struct sort_result_new results[nresults];
++      struct sort_order order[nresults];
++      struct addrinfo *q;
++      struct addrinfo *last = NULL;
++      char *canonname = NULL;
++      struct in6addrinfo *in6ai = NULL;
++      size_t in6ailen = 0;
++      bool seen_ipv4 = false;
++      bool seen_ipv6 = false;
++      /* We might need information about what interfaces are available.
++         Also determine whether we have IPv4 or IPv6 interfaces or both.  We
++         cannot cache the results since new interfaces could be added at
++         any time.  */
++      __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
++
++      /* We got all the source addresses we can get, now sort using
++       the information.  */
++      struct sort_result_combo src
++      = { .results = results, .nresults = nresults };
++
++      /* If we have information about deprecated and temporary addresses
++       sort the array now.  */
++      if (in6ai != NULL)
++      qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
++
++      int fd = -1;
++      int af = AF_UNSPEC;
++
++      for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
++      {
++        results[i].dest_addr = q;
++        results[i].native = -1;
++        order[i].index = i;
++        order[i].src = &src;
++
++        /* If we just looked up the address for a different
++           protocol, reuse the result.  */
++        if (last != NULL && last->ai_addrlen == q->ai_addrlen
++            && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
++          {
++            memcpy (&results[i].source_addr, &results[i - 1].source_addr,
++                    results[i - 1].source_addr_len);
++            results[i].source_addr_len = results[i - 1].source_addr_len;
++            results[i].got_source_addr = results[i - 1].got_source_addr;
++            results[i].source_addr_flags = results[i - 1].source_addr_flags;
++            results[i].prefixlen = results[i - 1].prefixlen;
++            results[i].index = results[i - 1].index;
++          }
++        else
++          {
++            results[i].got_source_addr = false;
++            results[i].source_addr_flags = 0;
++            results[i].prefixlen = 0;
++            results[i].index = 0xffffffffu;
++
++            /* We overwrite the type with SOCK_DGRAM since we do not
++               want connect() to connect to the other side.  If we
++               cannot determine the source address remember this
++               fact.  */
++            if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
++              {
++                if (fd != -1)
++                close_retry:
++                  close_not_cancel_no_status (fd);
++                af = q->ai_family;
++                fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
++              }
++            else
++              {
++                /* Reset the connection.  */
++                struct sockaddr sa = { .sa_family = AF_UNSPEC };
++                __connect (fd, &sa, sizeof (sa));
++              }
++
++            socklen_t sl = sizeof (results[i].source_addr);
++            if (fd != -1
++                && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
++                && __getsockname (fd,
++                                  (struct sockaddr *) &results[i].source_addr,
++                                  &sl) == 0)
++              {
++                results[i].source_addr_len = sl;
++                results[i].got_source_addr = true;
++
++                if (in6ai != NULL)
++                  {
++                    /* See whether the source address is on the list of
++                       deprecated or temporary addresses.  */
++                    struct in6addrinfo tmp;
++
++                    if (q->ai_family == AF_INET && af == AF_INET)
++                      {
++                        struct sockaddr_in *sinp
++                          = (struct sockaddr_in *) &results[i].source_addr;
++                        tmp.addr[0] = 0;
++                        tmp.addr[1] = 0;
++                        tmp.addr[2] = htonl (0xffff);
++                        tmp.addr[3] = sinp->sin_addr.s_addr;
++                      }
++                    else
++                      {
++                        struct sockaddr_in6 *sin6p
++                          = (struct sockaddr_in6 *) &results[i].source_addr;
++                        memcpy (tmp.addr, &sin6p->sin6_addr, IN6ADDRSZ);
++                      }
++
++                    struct in6addrinfo *found
++                      = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai),
++                                 in6aicmp);
++                    if (found != NULL)
++                      {
++                        results[i].source_addr_flags = found->flags;
++                        results[i].prefixlen = found->prefixlen;
++                        results[i].index = found->index;
++                      }
++                  }
++
++                if (q->ai_family == AF_INET && af == AF_INET6)
++                  {
++                    /* We have to convert the address.  The socket is
++                       IPv6 and the request is for IPv4.  */
++                    struct sockaddr_in6 *sin6
++                      = (struct sockaddr_in6 *) &results[i].source_addr;
++                    struct sockaddr_in *sin
++                      = (struct sockaddr_in *) &results[i].source_addr;
++                    assert (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32));
++                    sin->sin_family = AF_INET;
++                    /* We do not have to initialize sin_port since this
++                       fields has the same position and size in the IPv6
++                       structure.  */
++                    assert (offsetof (struct sockaddr_in, sin_port)
++                            == offsetof (struct sockaddr_in6, sin6_port));
++                    assert (sizeof (sin->sin_port)
++                            == sizeof (sin6->sin6_port));
++                    memcpy (&sin->sin_addr,
++                            &sin6->sin6_addr.s6_addr32[3], INADDRSZ);
++                    results[i].source_addr_len = sizeof (struct sockaddr_in);
++                  }
++              }
++            else if (errno == EAFNOSUPPORT && af == AF_INET6
++                     && q->ai_family == AF_INET)
++              /* This could mean IPv6 sockets are IPv6-only.  */
++              goto close_retry;
++            else
++              /* Just make sure that if we have to process the same
++                 address again we do not copy any memory.  */
++              results[i].source_addr_len = 0;
++          }
++
++        /* Remember the canonical name.  */
++        if (q->ai_canonname != NULL)
++          {
++            assert (canonname == NULL);
++            canonname = q->ai_canonname;
++            q->ai_canonname = NULL;
++          }
++      }
++
++      if (fd != -1)
++      close_not_cancel_no_status (fd);
++
++      if (__builtin_expect (gaiconf_reload_flag_ever_set, 0))
++      {
++        __libc_lock_define_initialized (static, lock);
++
++        __libc_lock_lock (lock);
++        if (gaiconf_reload_flag)
++          gaiconf_reload ();
++        qsort (order, nresults, sizeof (order[0]), rfc3484_new_sort);
++        __libc_lock_unlock (lock);
++      }
++      else
++      qsort (order, nresults, sizeof (order[0]), rfc3484_new_sort);
++
++      /* Queue the results up as they come out of sorting.  */
++      q = p = results[order[0].index].dest_addr;
++      for (i = 1; i < nresults; ++i)
++      q = q->ai_next = results[order[i].index].dest_addr;
++      q->ai_next = NULL;
++
++      /* Fill in the canonical name into the new first entry.  */
++      p->ai_canonname = canonname;
++
++      free (in6ai);
++    }
++do_ret:;
+   if (p)
+     {
+       *pai = p;
+--- libc/inet/Makefile.jj      2004-07-26 00:28:37.000000000 -0400
++++ libc/inet/Makefile 2007-12-14 22:52:11.000000000 -0500
+@@ -49,7 +49,7 @@ routines := htonl htons              \
+           getipv4sourcefilter setipv4sourcefilter \
+           getsourcefilter setsourcefilter
+-aux := check_pf ifreq
++aux := check_pf check_native ifreq
+ tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \
+        tst-gethnm test-ifaddrs bug-if1
+--- libc/posix/tst-rfc3484-2.c.jj      2007-11-13 10:14:11.610303087 -0500
++++ libc/posix/tst-rfc3484-2.c 2007-12-14 22:52:11.000000000 -0500
+@@ -0,0 +1,169 @@
++#include <stdbool.h>
++#include <stdio.h>
++#include <ifaddrs.h>
++
++/* Internal definitions used in the libc code.  */
++#define __getservbyname_r getservbyname_r
++#define __socket socket
++#define __getsockname getsockname
++#define __inet_aton inet_aton
++#define __gethostbyaddr_r gethostbyaddr_r
++#define __gethostbyname2_r gethostbyname2_r
++
++void
++attribute_hidden
++__check_pf (bool *p1, bool *p2, struct in6addrinfo **in6ai, size_t *in6ailen)
++{
++  *p1 = *p2 = true;
++  *in6ai = NULL;
++  *in6ailen = 0;
++}
++void
++attribute_hidden
++__check_native (uint32_t a1_index, int *a1_native,
++              uint32_t a2_index, int *a2_native)
++{
++}
++int
++__idna_to_ascii_lz (const char *input, char **output, int flags)
++{
++  return 0;
++}
++int
++__idna_to_unicode_lzlz (const char *input, char **output, int flags)
++{
++  *output = NULL;
++  return 0;
++}
++
++#include "../sysdeps/posix/getaddrinfo.c"
++
++service_user *__nss_hosts_database attribute_hidden;
++
++
++/* This is the beginning of the real test code.  The above defines
++   (among other things) the function rfc3484_sort.  */
++
++
++#if __BYTE_ORDER == __BIG_ENDIAN
++# define h(n) n
++#else
++# define h(n) __bswap_constant_32 (n)
++#endif
++
++
++ssize_t
++__getline (char **lineptr, size_t *n, FILE *s)
++{
++  *lineptr = NULL;
++  *n = 0;
++  return 0;
++}
++
++
++static int
++do_test (void)
++{
++  labels = default_labels_new;
++  precedence = default_precedence_new;
++  scopes = default_scopes;
++
++  struct sockaddr_in so1;
++  so1.sin_family = AF_INET;
++  so1.sin_addr.s_addr = h (0xc0a85f19);
++
++  struct sockaddr_in sa1;
++  sa1.sin_family = AF_INET;
++  sa1.sin_addr.s_addr = h (0xe0a85f19);
++
++  struct addrinfo ai1;
++  ai1.ai_family = AF_INET;
++  ai1.ai_addr = (struct sockaddr *) &sa1;
++
++  struct sockaddr_in6 so2;
++  so2.sin6_family = AF_INET6;
++  so2.sin6_addr.s6_addr32[0] = h (0xfec01234);
++  so2.sin6_addr.s6_addr32[1] = 1;
++  so2.sin6_addr.s6_addr32[2] = 1;
++  so2.sin6_addr.s6_addr32[3] = 1;
++
++  struct sockaddr_in6 sa2;
++  sa2.sin6_family = AF_INET6;
++  sa2.sin6_addr.s6_addr32[0] = h (0x07d10001);
++  sa2.sin6_addr.s6_addr32[1] = 1;
++  sa2.sin6_addr.s6_addr32[2] = 1;
++  sa2.sin6_addr.s6_addr32[3] = 1;
++
++  struct addrinfo ai2;
++  ai2.ai_family = AF_INET6;
++  ai2.ai_addr = (struct sockaddr *) &sa2;
++
++
++  struct sort_result_new results[2];
++  struct sort_result_combo combo = { .results = results, .nresults = 2 };
++  struct sort_order order[2];
++
++  results[0].dest_addr = &ai1;
++  results[0].got_source_addr = true;
++  results[0].source_addr_len = sizeof (so1);
++  results[0].source_addr_flags = 0;
++  results[0].prefixlen = 16;
++  results[0].index = 0;
++  memcpy (&results[0].source_addr, &so1, sizeof (so1));
++  order[0].index = 0;
++  order[0].src = &combo;
++
++  results[1].dest_addr = &ai2;
++  results[1].got_source_addr = true;
++  results[1].source_addr_len = sizeof (so2);
++  results[1].source_addr_flags = 0;
++  results[1].prefixlen = 16;
++  results[1].index = 0;
++  memcpy (&results[1].source_addr, &so2, sizeof (so2));
++  order[1].index = 1;
++  order[1].src = &combo;
++
++  qsort (order, 2, sizeof (order[0]), rfc3484_new_sort);
++
++  int result = 0;
++  if (results[order[0].index].dest_addr->ai_family == AF_INET6)
++    {
++      puts ("wrong order in first test");
++      result |= 1;
++    }
++
++
++  /* And again, this time with the reverse starting order.  */
++  results[1].dest_addr = &ai1;
++  results[1].got_source_addr = true;
++  results[1].source_addr_len = sizeof (so1);
++  results[1].source_addr_flags = 0;
++  results[1].prefixlen = 16;
++  results[1].index = 0;
++  memcpy (&results[1].source_addr, &so1, sizeof (so1));
++  order[1].index = 1;
++  order[1].src = &combo;
++
++  results[0].dest_addr = &ai2;
++  results[0].got_source_addr = true;
++  results[0].source_addr_len = sizeof (so2);
++  results[0].source_addr_flags = 0;
++  results[0].prefixlen = 16;
++  results[0].index = 0;
++  memcpy (&results[0].source_addr, &so2, sizeof (so2));
++  order[0].index = 0;
++  order[0].src = &combo;
++
++  qsort (order, 2, sizeof (order[0]), rfc3484_new_sort);
++
++  if (results[order[0].index].dest_addr->ai_family == AF_INET6)
++    {
++      puts ("wrong order in second test");
++      result |= 1;
++    }
++
++  return result;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/posix/tst-rfc3484-3.c.jj      2007-11-13 10:14:11.610303087 -0500
++++ libc/posix/tst-rfc3484-3.c 2007-12-14 22:52:11.000000000 -0500
+@@ -0,0 +1,139 @@
++#include <stdbool.h>
++#include <stdio.h>
++#include <ifaddrs.h>
++
++/* Internal definitions used in the libc code.  */
++#define __getservbyname_r getservbyname_r
++#define __socket socket
++#define __getsockname getsockname
++#define __inet_aton inet_aton
++#define __gethostbyaddr_r gethostbyaddr_r
++#define __gethostbyname2_r gethostbyname2_r
++
++void
++attribute_hidden
++__check_pf (bool *p1, bool *p2, struct in6addrinfo **in6ai, size_t *in6ailen)
++{
++  *p1 = *p2 = true;
++  *in6ai = NULL;
++  *in6ailen = 0;
++}
++void
++attribute_hidden
++__check_native (uint32_t a1_index, int *a1_native,
++              uint32_t a2_index, int *a2_native)
++{
++}
++int
++__idna_to_ascii_lz (const char *input, char **output, int flags)
++{
++  return 0;
++}
++int
++__idna_to_unicode_lzlz (const char *input, char **output, int flags)
++{
++  *output = NULL;
++  return 0;
++}
++
++#include "../sysdeps/posix/getaddrinfo.c"
++
++service_user *__nss_hosts_database attribute_hidden;
++
++
++/* This is the beginning of the real test code.  The above defines
++   (among other things) the function rfc3484_sort.  */
++
++
++#if __BYTE_ORDER == __BIG_ENDIAN
++# define h(n) n
++#else
++# define h(n) __bswap_constant_32 (n)
++#endif
++
++struct sockaddr_in addrs[] =
++{
++  { .sin_family = AF_INET, .sin_addr = { h (0xa0a86d1d) } },
++  { .sin_family = AF_INET, .sin_addr = { h (0xa0a85d03) } },
++  { .sin_family = AF_INET, .sin_addr = { h (0xa0a82c3d) } },
++  { .sin_family = AF_INET, .sin_addr = { h (0xa0a86002) } },
++  { .sin_family = AF_INET, .sin_addr = { h (0xa0a802f3) } },
++  { .sin_family = AF_INET, .sin_addr = { h (0xa0a80810) } },
++  { .sin_family = AF_INET, .sin_addr = { h (0xa0a85e02) } },
++  { .sin_family = AF_INET, .sin_addr = { h (0xac162311) } },
++  { .sin_family = AF_INET, .sin_addr = { h (0x0a324572) } }
++};
++#define naddrs (sizeof (addrs) / sizeof (addrs[0]))
++static struct addrinfo ais[naddrs];
++static struct sort_result_new results[naddrs];
++static struct sort_order order[naddrs];
++
++static const int expected[naddrs] =
++  {
++    8, 0, 1, 2, 3, 4, 5, 6, 7
++  };
++
++static const struct scopeentry new_scopes[] =
++  {
++    { { { 169, 254, 0, 0 } }, h (0xffff0000), 2 },
++    { { { 127, 0, 0, 0 } }, h (0xff000000), 2 },
++    { { { 10, 0, 0, 0 } }, h (0xff000000), 5 },
++    { { { 192, 168, 0, 0 } }, h(0xffff0000), 5 },
++    { { { 0, 0, 0, 0 } }, h (0x00000000), 14 }
++  };
++
++
++ssize_t
++__getline (char **lineptr, size_t *n, FILE *s)
++{
++  *lineptr = NULL;
++  *n = 0;
++  return 0;
++}
++
++
++static int
++do_test (void)
++{
++  labels = default_labels_new;
++  precedence = default_precedence_new;
++  scopes = new_scopes;
++
++  struct sockaddr_in so;
++  so.sin_family = AF_INET;
++  so.sin_addr.s_addr = h (0x0aa85f19);
++  struct sort_result_combo combo = { .results = results, .nresults = naddrs };
++
++  for (int i = 0; i < naddrs; ++i)
++    {
++      ais[i].ai_family = AF_INET;
++      ais[i].ai_addr = (struct sockaddr *) &addrs[i];
++      results[i].dest_addr = &ais[i];
++      results[i].got_source_addr = true;
++      memcpy(&results[i].source_addr, &so, sizeof (so));
++      results[i].source_addr_len = sizeof (so);
++      results[i].source_addr_flags = 0;
++      results[i].prefixlen = 8;
++      results[i].index = 0;
++      order[i].index = i;
++      order[i].src = &combo;
++    }
++
++  qsort (order, naddrs, sizeof (order[0]), rfc3484_new_sort);
++
++  int result = 0;
++  for (int i = 0; i < naddrs; ++i)
++    {
++      struct in_addr addr = ((struct sockaddr_in *) (results[order[i].index].dest_addr->ai_addr))->sin_addr;
++
++      int here = memcmp (&addr, &addrs[expected[i]].sin_addr,
++                       sizeof (struct in_addr));
++      printf ("[%d] = %s: %s\n", i, inet_ntoa (addr), here ? "FAIL" : "OK");
++      result |= here;
++    }
++
++  return result;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/posix/Makefile.jj     2007-12-14 22:52:09.000000000 -0500
++++ libc/posix/Makefile        2007-12-14 22:52:11.000000000 -0500
+@@ -88,7 +88,8 @@ tests                := tstgetopt testfnm runtests run
+                  tst-execvp1 tst-execvp2 tst-execlp1 tst-execlp2 \
+                  tst-execv1 tst-execv2 tst-execl1 tst-execl2 \
+                  tst-execve1 tst-execve2 tst-execle1 tst-execle2 \
+-                 tst-execvp3 tst-execvp4 tst-rfc3484
++                 tst-execvp3 tst-execvp4 tst-rfc3484 tst-rfc3484-2 \
++                 tst-rfc3484-3
+ xtests                := bug-ga2
+ ifeq (yes,$(build-shared))
+ test-srcs     := globtest
+--- libc/posix/tst-rfc3484.c.jj        2007-12-14 22:52:08.000000000 -0500
++++ libc/posix/tst-rfc3484.c   2007-12-14 22:52:11.000000000 -0500
+@@ -1,5 +1,6 @@
+ #include <stdbool.h>
+ #include <stdio.h>
++#include <ifaddrs.h>
+ /* Internal definitions used in the libc code.  */
+ #define __getservbyname_r getservbyname_r
+@@ -8,12 +9,21 @@
+ #define __inet_aton inet_aton
+ #define __gethostbyaddr_r gethostbyaddr_r
+ #define __gethostbyname2_r gethostbyname2_r
++#define __getline getline
+ void
+ attribute_hidden
+-__check_pf (bool *p1, bool *p2)
++__check_pf (bool *p1, bool *p2, struct in6addrinfo **in6ai, size_t *in6ailen)
+ {
+   *p1 = *p2 = true;
++  *in6ai = NULL;
++  *in6ailen = 0;
++}
++void
++attribute_hidden
++__check_native (uint32_t a1_index, int *a1_native,
++              uint32_t a2_index, int *a2_native)
++{
+ }
+ int
+ __idna_to_ascii_lz (const char *input, char **output, int flags)
+@@ -68,6 +78,8 @@ do_test (void)
+   so.sin_family = AF_INET;
+   so.sin_addr.s_addr = h (0xc0a85f19);
++  scopes = default_scopes;
++
+   for (int i = 0; i < naddrs; ++i)
+     {
+       ais[i].ai_family = AF_INET;
diff --git a/src/patches/glibc/glibc-rh403231.patch b/src/patches/glibc/glibc-rh403231.patch
new file mode 100644 (file)
index 0000000..b3629ca
--- /dev/null
@@ -0,0 +1,186 @@
+2007-12-16  Ulrich Drepper  <drepper@redhat.com>
+
+       * malloc/malloc.c (public_mTRIm): Iterate over all arenas and call
+       mTRIm for all of them.
+       (mTRIm): Additionally iterate over all free blocks and use madvise
+       to free memory for all those blocks which contain at least one
+       memory page.
+       * malloc/tst-trim1.c: New file.
+       * malloc/Makefile (tests): Add tst-trim1.
+
+--- libc/malloc/Makefile       21 May 2007 16:12:25 -0000      1.55
++++ libc/malloc/Makefile       16 Dec 2007 22:57:50 -0000      1.56
+@@ -26,7 +26,7 @@ all:
+ dist-headers := malloc.h
+ headers := $(dist-headers) obstack.h mcheck.h
+ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
+-       tst-mallocstate
++       tst-mallocstate tst-trim1
+ test-srcs = tst-mtrace
+ distribute = thread-m.h mtrace.pl mcheck-init.c stackinfo.h memusage.h \
+--- libc/malloc/malloc.c       11 Dec 2007 23:46:31 -0000      1.182
++++ libc/malloc/malloc.c       16 Dec 2007 22:52:58 -0000      1.183
+@@ -1509,7 +1509,7 @@ static Void_t*  _int_pvalloc(mstate, siz
+ /*static Void_t*  cALLOc(size_t, size_t);*/
+ static Void_t** _int_icalloc(mstate, size_t, size_t, Void_t**);
+ static Void_t** _int_icomalloc(mstate, size_t, size_t*, Void_t**);
+-static int      mTRIm(size_t);
++static int      mTRIm(mstate, size_t);
+ static size_t   mUSABLe(Void_t*);
+ static void     mSTATs(void);
+ static int      mALLOPt(int, int);
+@@ -3794,13 +3794,22 @@ public_cFREe(Void_t* m)
+ int
+ public_mTRIm(size_t s)
+ {
+-  int result;
++  int result = 0;
+   if(__malloc_initialized < 0)
+     ptmalloc_init ();
+-  (void)mutex_lock(&main_arena.mutex);
+-  result = mTRIm(s);
+-  (void)mutex_unlock(&main_arena.mutex);
++
++  mstate ar_ptr = &main_arena;
++  do
++    {
++      (void) mutex_lock (&ar_ptr->mutex);
++      result |= mTRIm (ar_ptr, s);
++      (void) mutex_unlock (&ar_ptr->mutex);
++
++      ar_ptr = ar_ptr->next;
++    }
++  while (ar_ptr != &main_arena);
++
+   return result;
+ }
+@@ -5186,20 +5195,60 @@ _int_pvalloc(av, bytes) mstate av, size_
+ */
+ #if __STD_C
+-int mTRIm(size_t pad)
++static int mTRIm(mstate av, size_t pad)
+ #else
+-int mTRIm(pad) size_t pad;
++static int mTRIm(av, pad) mstate av; size_t pad;
+ #endif
+ {
+-  mstate av = &main_arena; /* already locked */
+-
+   /* Ensure initialization/consolidation */
+-  malloc_consolidate(av);
++  malloc_consolidate (av);
++
++  const size_t ps = mp_.pagesize;
++  int psindex = bin_index (ps);
++  const size_t psm1 = ps - 1;
++
++  int result = 0;
++  for (int i = 1; i < NBINS; ++i)
++    if (i == 1 || i >= psindex)
++      {
++        mbinptr bin = bin_at (av, i);
++
++        for (mchunkptr p = last (bin); p != bin; p = p->bk)
++        {
++          INTERNAL_SIZE_T size = chunksize (p);
++
++          if (size > psm1 + sizeof (struct malloc_chunk))
++            {
++              /* See whether the chunk contains at least one unused page.  */
++              char *paligned_mem = (char *) (((uintptr_t) p
++                                              + sizeof (struct malloc_chunk)
++                                              + psm1) & ~psm1);
++
++              assert ((char *) chunk2mem (p) + 4 * SIZE_SZ <= paligned_mem);
++              assert ((char *) p + size > paligned_mem);
++
++              /* This is the size we could potentially free.  */
++              size -= paligned_mem - (char *) p;
++
++              if (size > psm1)
++                {
++#ifdef MALLOC_DEBUG
++                  /* When debugging we simulate destroying the memory
++                     content.  */
++                  memset (paligned_mem, 0x89, size & ~psm1);
++#endif
++                  madvise (paligned_mem, size & ~psm1, MADV_DONTNEED);
++
++                  result = 1;
++                }
++            }
++        }
++      }
+ #ifndef MORECORE_CANNOT_TRIM
+-  return sYSTRIm(pad, av);
++  return result | (av == &main_arena ? sYSTRIm (pad, av) : 0);
+ #else
+-  return 0;
++  return result;
+ #endif
+ }
+--- libc/malloc/tst-trim1.c    1 Jan 1970 00:00:00 -0000
++++ libc/malloc/tst-trim1.c    16 Dec 2007 22:57:25 -0000      1.1
+@@ -0,0 +1,56 @@
++#include <malloc.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#define N 10000
++
++static void *arr[N];
++
++static int
++do_test (void)
++{
++  for (int i = 0; i < N; ++i)
++    {
++      size_t size = random () % 16384;
++
++      if ((arr[i] = malloc (size)) == NULL)
++      {
++      nomem:
++        puts ("not enough memory");
++        return 0;
++      }
++
++      memset (arr[i], size, size);
++    }
++
++  void *p = malloc (256);
++  if (p == NULL)
++    goto nomem;
++  memset (p, 1, 256);
++
++  puts ("==================================================================");
++
++  for (int i = 0; i < N; ++i)
++    if (i % 13 != 0)
++      free (arr[i]);
++
++  puts ("==================================================================");
++
++  malloc_trim (0);
++
++  puts ("==================================================================");
++
++  p = malloc (30000);
++  if (p == NULL)
++    goto nomem;
++
++  memset (p, 2, 30000);
++
++  malloc_trim (0);
++
++  return 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-rh405781.patch b/src/patches/glibc/glibc-rh405781.patch
new file mode 100644 (file)
index 0000000..b2b81f1
--- /dev/null
@@ -0,0 +1,21 @@
+2007-12-17  Ulrich Drepper  <drepper@redhat.com>
+
+       * malloc/malloc.c (public_cALLOc): For arena other than
+       main_arena, count all bytes inside the mprotect_size range of the
+       heap as uninitialized.
+
+--- libc/malloc/malloc.c       16 Dec 2007 22:52:58 -0000      1.183
++++ libc/malloc/malloc.c       17 Dec 2007 18:43:50 -0000      1.184
+@@ -3886,6 +3886,12 @@ public_cALLOc(size_t n, size_t elem_size
+       oldtopsize < mp_.sbrk_base + av->max_system_mem - (char *)oldtop)
+     oldtopsize = (mp_.sbrk_base + av->max_system_mem - (char *)oldtop);
+ #endif
++  if (av != &main_arena)
++    {
++      heap_info *heap = heap_for_ptr (oldtop);
++      if (oldtopsize < (char *) heap + heap->mprotect_size - (char *) oldtop)
++      oldtopsize = (char *) heap + heap->mprotect_size - (char *) oldtop;
++    }
+ #endif
+   mem = _int_malloc(av, sz);
diff --git a/src/patches/glibc/glibc-rh428859.patch b/src/patches/glibc/glibc-rh428859.patch
new file mode 100644 (file)
index 0000000..d15ff8e
--- /dev/null
@@ -0,0 +1,10 @@
+--- libc/fedora/glibc_post_upgrade.c   25 Aug 2007 19:15:32 -0000      1.1.2.10
++++ libc/fedora/glibc_post_upgrade.c   28 Mar 2008 14:05:57 -0000      1.1.2.11
+@@ -182,6 +182,7 @@ main (void)
+   /* Check if we can safely condrestart sshd.  */
+   if (access ("/sbin/service", X_OK) == 0
+       && access ("/usr/sbin/sshd", X_OK) == 0
++      && access ("/etc/rc.d/init.d/sshd", X_OK) == 0
+       && access ("/bin/bash", X_OK) == 0)
+     {
+       if (check_elf ("/usr/sbin/sshd"))
diff --git a/src/patches/glibc/glibc-rh434601.patch b/src/patches/glibc/glibc-rh434601.patch
new file mode 100644 (file)
index 0000000..ecfe51e
--- /dev/null
@@ -0,0 +1,18 @@
+2008-03-11  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
+       (__lll_mutex_timedlock_wait): Use correct pointer when we don't
+       call into the kernel to delay and cmpxchgl fails. Patch by
+       Bryan Mason <bmason@redhat.com>.
+
+--- libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S.jj 2007-06-22 11:46:42.000000000 -0400
++++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S    2008-03-11 06:07:39.000000000 -0400
+@@ -201,7 +201,7 @@ __lll_mutex_timedlock_wait:
+       /* Make sure the current holder knows we are going to sleep.  */
+       movl    %edx, %eax
+-      xchgl   %eax, (%rdi)
++      xchgl   %eax, (%r12)
+       testl   %eax, %eax
+       jz      6b
+       jmp     1b
diff --git a/src/patches/glibc/glibc-rh437571.patch b/src/patches/glibc/glibc-rh437571.patch
new file mode 100644 (file)
index 0000000..7ae39e6
--- /dev/null
@@ -0,0 +1,469 @@
+2007-01-03  Jakub Jelinek  <jakub@redhat.com>
+
+       * posix/execvp.c: Include alloca.h.
+       (allocate_scripts_argv): Renamed to...
+       (scripts_argv): ... this.  Don't allocate buffer here nor count
+       arguments.
+       (execvp): Use alloca if possible.
+       * posix/Makefile: Add rules to build and run tst-vfork3 test.
+       * posix/tst-vfork3.c: New test.
+
+--- libc/posix/Makefile        7 Sep 2006 13:50:05 -0000       1.193
++++ libc/posix/Makefile        3 Jan 2007 23:02:10 -0000       1.194
+@@ -83,7 +83,7 @@
+                  bug-regex25 bug-regex26 bug-regex27 bug-regex28 \
+                  tst-nice tst-nanosleep tst-regex2 \
+                  transbug tst-rxspencer tst-pcre tst-boost \
+-                 bug-ga1 tst-vfork1 tst-vfork2 tst-waitid \
++                 bug-ga1 tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \
+                  tst-getaddrinfo2 bug-glob1 bug-glob2 tst-sysconf \
+                  tst-execvp1 tst-execvp2 tst-execlp1 tst-execlp2 \
+                  tst-execv1 tst-execv2 tst-execl1 tst-execl2 \
+@@ -108,7 +108,7 @@
+            tst-rxspencer-mem tst-rxspencer.mtrace tst-getconf.out \
+            tst-pcre-mem tst-pcre.mtrace tst-boost-mem tst-boost.mtrace \
+            bug-ga2.mtrace bug-ga2-mem bug-glob2.mtrace bug-glob2-mem \
+-           getconf.speclist
++           tst-vfork3-mem tst-vfork3.mtrace getconf.speclist
+ include ../Rules
+@@ -174,6 +174,7 @@
+ tst-spawn-ARGS = -- $(built-program-cmd)
+ tst-dir-ARGS = `pwd` `cd $(common-objdir)/$(subdir); pwd` `cd $(common-objdir); pwd` $(objpfx)tst-dir
+ tst-chmod-ARGS = `pwd`
++tst-vfork3-ARGS = --test-dir=$(objpfx)
+ tst-fnmatch-ENV = LOCPATH=$(common-objpfx)localedata
+ tst-regexloc-ENV = LOCPATH=$(common-objpfx)localedata
+@@ -218,7 +219,7 @@
+ tests: $(objpfx)bug-regex2-mem $(objpfx)bug-regex14-mem \
+   $(objpfx)bug-regex21-mem $(objpfx)tst-rxspencer-mem \
+   $(objpfx)tst-pcre-mem $(objpfx)tst-boost-mem $(objpfx)tst-getconf.out \
+-  $(objpfx)bug-glob2-mem
++  $(objpfx)bug-glob2-mem $(objpfx)tst-vfork3-mem
+ xtests: $(objpfx)bug-ga2-mem
+ endif
+@@ -245,6 +246,11 @@
+ $(objpfx)bug-regex21-mem: $(objpfx)bug-regex21.out
+       $(common-objpfx)malloc/mtrace $(objpfx)bug-regex21.mtrace > $@
++tst-vfork3-ENV = MALLOC_TRACE=$(objpfx)tst-vfork3.mtrace
++
++$(objpfx)tst-vfork3-mem: $(objpfx)tst-vfork3.out
++      $(common-objpfx)malloc/mtrace $(objpfx)tst-vfork3.mtrace > $@
++
+ # tst-rxspencer.mtrace is generated only when run without --utf8
+ # option, since otherwise the file has almost 100M and takes very long
+ # time to process.
+--- libc/posix/execvp.c        24 Jul 2005 21:38:43 -0000      1.26
++++ libc/posix/execvp.c        3 Jan 2007 23:01:15 -0000       1.27
+@@ -16,6 +17,7 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
++#include <alloca.h>
+ #include <unistd.h>
+ #include <stdarg.h>
+ #include <stdbool.h>
+@@ -27,29 +29,18 @@
+ /* The file is accessible but it is not an executable file.  Invoke
+    the shell to interpret it as a script.  */
+-static char **
++static void
+ internal_function
+-allocate_scripts_argv (const char *file, char *const argv[])
++scripts_argv (const char *file, char *const argv[], int argc, char **new_argv)
+ {
+-  /* Count the arguments.  */
+-  int argc = 0;
+-  while (argv[argc++])
+-    ;
+-
+   /* Construct an argument list for the shell.  */
+-  char **new_argv = (char **) malloc ((argc + 1) * sizeof (char *));
+-  if (new_argv != NULL)
++  new_argv[0] = (char *) _PATH_BSHELL;
++  new_argv[1] = (char *) file;
++  while (argc > 1)
+     {
+-      new_argv[0] = (char *) _PATH_BSHELL;
+-      new_argv[1] = (char *) file;
+-      while (argc > 1)
+-      {
+-        new_argv[argc] = argv[argc - 1];
+-        --argc;
+-      }
++      new_argv[argc] = argv[argc - 1];
++      --argc;
+     }
+-
+-  return new_argv;
+ }
+@@ -67,8 +58,6 @@ execvp (file, argv)
+       return -1;
+     }
+-  char **script_argv = NULL;
+-
+   if (strchr (file, '/') != NULL)
+     {
+       /* Don't search when it contains a slash.  */
+@@ -76,46 +65,71 @@ execvp (file, argv)
+       if (errno == ENOEXEC)
+       {
+-        script_argv = allocate_scripts_argv (file, argv);
++        /* Count the arguments.  */
++        int argc = 0;
++        while (argv[argc++])
++          ;
++        size_t len = (argc + 1) * sizeof (char *);
++        char **script_argv;
++        void *ptr = NULL;
++        if (__libc_use_alloca (len))
++          script_argv = alloca (len);
++        else
++          script_argv = ptr = malloc (len);
++
+         if (script_argv != NULL)
+           {
++            scripts_argv (file, argv, argc, script_argv);
+             __execve (script_argv[0], script_argv, __environ);
+-            free (script_argv);
++            free (ptr);
+           }
+       }
+     }
+   else
+     {
++      size_t pathlen;
++      size_t alloclen = 0;
+       char *path = getenv ("PATH");
++      if (path == NULL)
++      {
++        pathlen = confstr (_CS_PATH, (char *) NULL, 0);
++        alloclen = pathlen + 1;
++      }
++      else
++      pathlen = strlen (path);
++
++      size_t len = strlen (file) + 1;
++      alloclen += pathlen + len + 1;
++
++      char *name;
+       char *path_malloc = NULL;
++      if (__libc_use_alloca (alloclen))
++      name = alloca (alloclen);
++      else
++      {
++        path_malloc = name = malloc (alloclen);
++        if (name == NULL)
++          return -1;
++      }
++
+       if (path == NULL)
+       {
+         /* There is no `PATH' in the environment.
+            The default search path is the current directory
+            followed by the path `confstr' returns for `_CS_PATH'.  */
+-        size_t len = confstr (_CS_PATH, (char *) NULL, 0);
+-        path = (char *) malloc (1 + len);
+-        if (path == NULL)
+-          return -1;
++        path = name + pathlen + len + 1;
+         path[0] = ':';
+-        (void) confstr (_CS_PATH, path + 1, len);
+-        path_malloc = path;
++        (void) confstr (_CS_PATH, path + 1, pathlen);
+       }
+-      size_t len = strlen (file) + 1;
+-      size_t pathlen = strlen (path);
+-      char *name = malloc (pathlen + len + 1);
+-      if (name == NULL)
+-      {
+-        free (path_malloc);
+-        return -1;
+-      }
+       /* Copy the file name at the top.  */
+       name = (char *) memcpy (name + pathlen + 1, file, len);
+       /* And add the slash.  */
+       *--name = '/';
++      char **script_argv = NULL;
++      void *script_argv_malloc = NULL;
+       bool got_eacces = false;
+       char *p = path;
+       do
+@@ -139,7 +153,15 @@ execvp (file, argv)
+           {
+             if (script_argv == NULL)
+               {
+-                script_argv = allocate_scripts_argv (startp, argv);
++                /* Count the arguments.  */
++                int argc = 0;
++                while (argv[argc++])
++                  ;
++                size_t arglen = (argc + 1) * sizeof (char *);
++                if (__libc_use_alloca (alloclen + arglen))
++                  script_argv = alloca (arglen);
++                else
++                  script_argv = script_argv_malloc = malloc (arglen);
+                 if (script_argv == NULL)
+                   {
+                     /* A possible EACCES error is not as important as
+@@ -147,6 +169,7 @@ execvp (file, argv)
+                     got_eacces = false;
+                     break;
+                   }
++                scripts_argv (startp, argv, argc, script_argv);
+               }
+             __execve (script_argv[0], script_argv, __environ);
+@@ -184,11 +207,10 @@ execvp (file, argv)
+       /* We tried every element and none of them worked.  */
+       if (got_eacces)
+       /* At least one failure was due to permissions, so report that
+-           error.  */
++         error.  */
+       __set_errno (EACCES);
+-      free (script_argv);
+-      free (name - pathlen);
++      free (script_argv_malloc);
+       free (path_malloc);
+     }
+--- libc/posix/tst-vfork3.c    1 Jan 1970 00:00:00 -0000
++++ libc/posix/tst-vfork3.c    3 Jan 2007 23:01:58 -0000       1.1
+@@ -0,0 +1,224 @@
++/* Test for vfork functions.
++   Copyright (C) 2007 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Jakub Jelinek <jakub@redhat.com>, 2007.
++
++   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 <errno.h>
++#include <fcntl.h>
++#include <mcheck.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/wait.h>
++
++static int do_test (void);
++static void do_prepare (void);
++char *tmpdirname;
++
++#define TEST_FUNCTION do_test ()
++#define PREPARE(argc, argv) do_prepare ()
++#include "../test-skeleton.c"
++
++static int
++do_test (void)
++{
++  mtrace ();
++
++  const char *path = getenv ("PATH");
++  if (path == NULL)
++    path = "/bin";
++  char pathbuf[strlen (tmpdirname) + 1 + strlen (path) + 1];
++  strcpy (stpcpy (stpcpy (pathbuf, tmpdirname), ":"), path);
++  if (setenv ("PATH", pathbuf, 1) < 0)
++    {
++      puts ("setenv failed");
++      return 1;
++    }
++
++  size_t i;
++  char *argv[3] = { (char *) "script1.sh", (char *) "1", NULL };
++  for (i = 0; i < 5; i++)
++    {
++      pid_t pid = vfork ();
++      if (pid < 0)
++      {
++        printf ("vfork failed: %m\n");
++        return 1;
++      }
++      else if (pid == 0)
++      {
++        execvp ("script1.sh", argv);
++        _exit (errno);
++      }
++      int status;
++      if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
++      {
++        puts ("waitpid failed");
++        return 1;
++      }
++      else if (status != 0)
++      {
++        if (WIFEXITED (status))
++          printf ("script1.sh failed with status %d\n",
++                  WEXITSTATUS (status));
++        else
++          printf ("script1.sh kill by signal %d\n",
++                  WTERMSIG (status));
++        return 1;
++      }
++    }
++
++  argv[0] = (char *) "script2.sh";
++  argv[1] = (char *) "2";
++  for (i = 0; i < 5; i++)
++    {
++      pid_t pid = vfork ();
++      if (pid < 0)
++      {
++        printf ("vfork failed: %m\n");
++        return 1;
++      }
++      else if (pid == 0)
++      {
++        execvp ("script2.sh", argv);
++        _exit (errno);
++      }
++      int status;
++      if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
++      {
++        puts ("waitpid failed");
++        return 1;
++      }
++      else if (status != 0)
++      {
++        printf ("script2.sh failed with status %d\n", status);
++        return 1;
++      }
++    }
++
++  for (i = 0; i < 5; i++)
++    {
++      pid_t pid = vfork ();
++      if (pid < 0)
++      {
++        printf ("vfork failed: %m\n");
++        return 1;
++      }
++      else if (pid == 0)
++      {
++        execlp ("script2.sh", "script2.sh", "3", NULL);
++        _exit (errno);
++      }
++      int status;
++      if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
++      {
++        puts ("waitpid failed");
++        return 1;
++      }
++      else if (status != 0)
++      {
++        printf ("script2.sh failed with status %d\n", status);
++        return 1;
++      }
++    }
++
++  unsetenv ("PATH");
++  argv[0] = (char *) "echo";
++  argv[1] = (char *) "script 4";
++  for (i = 0; i < 5; i++)
++    {
++      pid_t pid = vfork ();
++      if (pid < 0)
++      {
++        printf ("vfork failed: %m\n");
++        return 1;
++      }
++      else if (pid == 0)
++      {
++        execvp ("echo", argv);
++        _exit (errno);
++      }
++      int status;
++      if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
++      {
++        puts ("waitpid failed");
++        return 1;
++      }
++      else if (status != 0)
++      {
++        printf ("echo failed with status %d\n", status);
++        return 1;
++      }
++    }
++
++  return 0;
++}
++
++static void
++do_prepare (void)
++{
++  size_t len = strlen (test_dir) + sizeof ("/tst-vfork3.XXXXXX");
++  tmpdirname = malloc (len);
++  char *script1 = malloc (len + sizeof "/script1.sh");
++  char *script2 = malloc (len + sizeof "/script2.sh");
++  if (tmpdirname == NULL || script1 == NULL || script2 == NULL)
++    {
++      puts ("out of memory");
++      exit (1);
++    }
++  strcpy (stpcpy (tmpdirname, test_dir), "/tst-vfork3.XXXXXX");
++
++  tmpdirname = mkdtemp (tmpdirname);
++  if (tmpdirname == NULL)
++    {
++      puts ("could not create temporary directory");
++      exit (1);
++    }
++
++  strcpy (stpcpy (script1, tmpdirname), "/script1.sh");
++  strcpy (stpcpy (script2, tmpdirname), "/script2.sh");
++
++  /* Need to make sure tmpdirname is at the end of the linked list.  */
++  add_temp_file (script1);
++  add_temp_file (tmpdirname);
++  add_temp_file (script2);
++
++  const char content1[] = "#!/bin/sh\necho script $1\n";
++  int fd = open (script1, O_WRONLY | O_CREAT, 0700);
++  if (fd < 0
++      || TEMP_FAILURE_RETRY (write (fd, content1, sizeof content1))
++       != sizeof content1
++      || fchmod (fd, S_IRUSR | S_IXUSR) < 0)
++    {
++      printf ("Could not write %s\n", script1);
++      exit (1);
++    }
++  close (fd);
++
++  const char content2[] = "echo script $1\n";
++  fd = open (script2, O_WRONLY | O_CREAT, 0700);
++  if (fd < 0
++      || TEMP_FAILURE_RETRY (write (fd, content2, sizeof content2))
++       != sizeof content2
++      || fchmod (fd, S_IRUSR | S_IXUSR) < 0)
++    {
++      printf ("Could not write %s\n", script2);
++      exit (1);
++    }
++  close (fd);
++}
diff --git a/src/patches/glibc/glibc-rh455360.patch b/src/patches/glibc/glibc-rh455360.patch
new file mode 100644 (file)
index 0000000..125247d
--- /dev/null
@@ -0,0 +1,30 @@
+2008-07-15  Ulrich Drepper  <drepper@redhat.com>
+
+       * stdio-common/vfprintf.c (_IO_helper_overflow): In case _IO_sputn
+       doesn't manage to write anything, fail.
+
+--- libc/stdio-common/vfprintf.c       8 Apr 2008 07:59:50 -0000       1.128.2.13
++++ libc/stdio-common/vfprintf.c       16 Jul 2008 09:47:15 -0000
+@@ -2080,6 +2080,11 @@ _IO_helper_overflow (_IO_FILE *s, int c)
+     {
+       _IO_size_t written = _IO_sputn (target, s->_wide_data->_IO_write_base,
+                                     used);
++      if (written == 0 || written == WEOF)
++      return WEOF;
++      __wmemmove (s->_wide_data->_IO_write_base,
++                s->_wide_data->_IO_write_base + written,
++                used - written);
+       s->_wide_data->_IO_write_ptr -= written;
+     }
+ #else
+@@ -2087,6 +2092,10 @@ _IO_helper_overflow (_IO_FILE *s, int c)
+   if (used)
+     {
+       _IO_size_t written = _IO_sputn (target, s->_IO_write_base, used);
++      if (written == 0 || written == EOF)
++      return EOF;
++      memmove (s->_IO_write_base, s->_IO_write_base + written,
++             used - written);
+       s->_IO_write_ptr -= written;
+     }
+ #endif
diff --git a/src/patches/glibc/glibc-rh461481.patch b/src/patches/glibc/glibc-rh461481.patch
new file mode 100644 (file)
index 0000000..b443083
--- /dev/null
@@ -0,0 +1,96 @@
+2008-09-12  Flavio Leitner  <fleitner@redhat.com>
+            Ulrich Drepper  <drepper@redhat.com>
+
+       * malloc/malloc.c (public_vALLOc): Try other arenas in case
+       _int_valloc fails.
+       (public_pVALLOc): Likewise.
+
+--- libc/malloc/malloc.c       4 Mar 2008 18:36:04 -0000       1.188
++++ libc/malloc/malloc.c       12 Sep 2008 18:18:25 -0000      1.189
+@@ -3800,17 +3800,39 @@ public_vALLOc(size_t bytes)
+   if(__malloc_initialized < 0)
+     ptmalloc_init ();
++  size_t pagesz = mp_.pagesize;
++
+   __malloc_ptr_t (*hook) __MALLOC_PMT ((size_t, size_t,
+                                       __const __malloc_ptr_t)) =
+     __memalign_hook;
+   if (hook != NULL)
+-    return (*hook)(mp_.pagesize, bytes, RETURN_ADDRESS (0));
++    return (*hook)(pagesz, bytes, RETURN_ADDRESS (0));
+-  arena_get(ar_ptr, bytes + mp_.pagesize + MINSIZE);
++  arena_get(ar_ptr, bytes + pagesz + MINSIZE);
+   if(!ar_ptr)
+     return 0;
+   p = _int_valloc(ar_ptr, bytes);
+   (void)mutex_unlock(&ar_ptr->mutex);
++  if(!p) {
++    /* Maybe the failure is due to running out of mmapped areas. */
++    if(ar_ptr != &main_arena) {
++      (void)mutex_lock(&main_arena.mutex);
++      p = _int_memalign(&main_arena, pagesz, bytes);
++      (void)mutex_unlock(&main_arena.mutex);
++    } else {
++#if USE_ARENAS
++      /* ... or sbrk() has failed and there is still a chance to mmap() */
++      ar_ptr = arena_get2(ar_ptr->next ? ar_ptr : 0, bytes);
++      if(ar_ptr) {
++        p = _int_memalign(ar_ptr, pagesz, bytes);
++        (void)mutex_unlock(&ar_ptr->mutex);
++      }
++#endif
++    }
++  }
++  assert(!p || chunk_is_mmapped(mem2chunk(p)) ||
++       ar_ptr == arena_for_chunk(mem2chunk(p)));
++
+   return p;
+ }
+@@ -3823,17 +3845,40 @@ public_pVALLOc(size_t bytes)
+   if(__malloc_initialized < 0)
+     ptmalloc_init ();
++  size_t pagesz = mp_.pagesize;
++  size_t page_mask = mp_.pagesize - 1;
++  size_t rounded_bytes = (bytes + page_mask) & ~(page_mask);
++
+   __malloc_ptr_t (*hook) __MALLOC_PMT ((size_t, size_t,
+                                       __const __malloc_ptr_t)) =
+     __memalign_hook;
+   if (hook != NULL)
+-    return (*hook)(mp_.pagesize,
+-                 (bytes + mp_.pagesize - 1) & ~(mp_.pagesize - 1),
+-                 RETURN_ADDRESS (0));
++    return (*hook)(pagesz, rounded_bytes, RETURN_ADDRESS (0));
+-  arena_get(ar_ptr, bytes + 2*mp_.pagesize + MINSIZE);
++  arena_get(ar_ptr, bytes + 2*pagesz + MINSIZE);
+   p = _int_pvalloc(ar_ptr, bytes);
+   (void)mutex_unlock(&ar_ptr->mutex);
++  if(!p) {
++    /* Maybe the failure is due to running out of mmapped areas. */
++    if(ar_ptr != &main_arena) {
++      (void)mutex_lock(&main_arena.mutex);
++      p = _int_memalign(&main_arena, pagesz, rounded_bytes);
++      (void)mutex_unlock(&main_arena.mutex);
++    } else {
++#if USE_ARENAS
++      /* ... or sbrk() has failed and there is still a chance to mmap() */
++      ar_ptr = arena_get2(ar_ptr->next ? ar_ptr : 0,
++                        bytes + 2*pagesz + MINSIZE);
++      if(ar_ptr) {
++        p = _int_memalign(ar_ptr, pagesz, rounded_bytes);
++        (void)mutex_unlock(&ar_ptr->mutex);
++      }
++#endif
++    }
++  }
++  assert(!p || chunk_is_mmapped(mem2chunk(p)) ||
++       ar_ptr == arena_for_chunk(mem2chunk(p)));
++
+   return p;
+ }
diff --git a/src/patches/glibc/glibc-rh464146.patch b/src/patches/glibc/glibc-rh464146.patch
new file mode 100644 (file)
index 0000000..c277ec5
--- /dev/null
@@ -0,0 +1,27 @@
+2008-09-22  Deborah S. Townsend  <dstownse@us.ibm.com>
+
+       * sysdeps/s390/s390-64/s390x-mcount.S: Replace ahi with aghi.
+       * sysdeps/unix/sysv/linux/s390/s390-64/socket.S: Likewise.
+
+--- libc/sysdeps/s390/s390-64/s390x-mcount.S   26 May 2005 14:30:45 -0000      1.3
++++ libc/sysdeps/s390/s390-64/s390x-mcount.S   23 Sep 2008 17:17:30 -0000      1.4
+@@ -64,7 +64,7 @@ C_LABEL(_mcount)
+       /* Pop the saved registers.  Please note that `mcount' has no
+          return value.  */
+       lmg   %r14,%r5,160(%r15)
+-        ahi   %r15,224
++        aghi   %r15,224
+         br    %r14
+       ASM_SIZE_DIRECTIVE(C_SYMBOL_NAME(_mcount))
+--- libc/sysdeps/unix/sysv/linux/s390/s390-64/socket.S 20 Dec 2005 06:55:02 -0000      1.7
++++ libc/sysdeps/unix/sysv/linux/s390/s390-64/socket.S 23 Sep 2008 17:17:30 -0000      1.8
+@@ -61,7 +61,7 @@ ENTRY(__socket)
+       cfi_offset (%r6,-112)
+         lgr     %r1,%r15
+         lg      %r0,8(%r15)             /* Load eos.  */
+-        ahi     %r15,-208               /* Buy stack space.  */
++        aghi     %r15,-208              /* Buy stack space.  */
+       cfi_adjust_cfa_offset (208)
+         stg     %r1,0(%r15)             /* Store back chain.  */
+         stg     %r0,8(%r15)             /* Store eos.  */
diff --git a/src/patches/glibc/glibc-rh467309.patch b/src/patches/glibc/glibc-rh467309.patch
new file mode 100644 (file)
index 0000000..d5e52be
--- /dev/null
@@ -0,0 +1,140 @@
+2008-10-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * elf/Makefile: Add rules to build and run tst-tls17.
+       * elf/tst-tls17.c: New test.
+       * elf/tst-tlsmod17a.c: New file.
+       * elf/tst-tlsmod17b.c: Likewise.
+
+2008-10-16  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/generic/dl-tls.c (_dl_update_slotinfo): Copy all of the
+       initial DTV.
+
+--- libc/elf/Makefile  19 Aug 2008 00:18:58 -0000      1.328
++++ libc/elf/Makefile  17 Oct 2008 15:23:58 -0000      1.329
+@@ -158,7 +158,7 @@ tests += loadtest restest1 preloadtest l
+        neededtest3 neededtest4 unload2 lateglobal initfirst global \
+        restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \
+        circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \
+-       tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-align \
++       tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls17 tst-align \
+        tst-align2 $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \
+        tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
+        unload3 unload4 unload5 unload6 unload7 tst-global1 order2 \
+@@ -174,6 +174,7 @@ ifeq (yesyes,$(have-fpie)$(build-shared)
+ tests: $(objpfx)tst-pie1.out
+ endif
+ tests: $(objpfx)tst-leaks1-mem
++tlsmod17a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
+               testobj1_1 failobj constload2 constload3 unloadmod \
+               dep1 dep2 dep3 dep4 $(modules-vis-$(have-protected)) \
+@@ -191,6 +192,8 @@ modules-names = testobj1 testobj2 testob
+               tst-tlsmod5 tst-tlsmod6 tst-tlsmod7 tst-tlsmod8 \
+               tst-tlsmod9 tst-tlsmod10 tst-tlsmod11 tst-tlsmod12 \
+               tst-tlsmod13 tst-tlsmod13a tst-tlsmod14a tst-tlsmod14b \
++              $(patsubst %,tst-tlsmod17a%,$(tlsmod17a-suffixes)) \
++              tst-tlsmod17b \
+               circlemod1 circlemod1a circlemod2 circlemod2a \
+               circlemod3 circlemod3a \
+               reldep8mod1 reldep8mod2 reldep8mod3 \
+@@ -694,6 +697,13 @@ $(objpfx)tst-tls13.out: $(objpfx)tst-tls
+ $(objpfx)tst-tls14:  $(objpfx)tst-tlsmod14a.so $(libdl)
+ $(objpfx)tst-tls14.out:$(objpfx)tst-tlsmod14b.so
++$(objpfx)tst-tls17: $(libdl)
++$(objpfx)tst-tls17.out: $(objpfx)tst-tlsmod17b.so
++$(patsubst %,$(objpfx)tst-tlsmod17a%.os,$(tlsmod17a-suffixes)): $(objpfx)tst-tlsmod17a%.os : tst-tlsmod17a.c
++      $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ -DN=$* -DNOT_IN_libc=1 $<
++$(patsubst %,$(objpfx)tst-tlsmod17a%.so,$(tlsmod17a-suffixes)): $(objpfx)tst-tlsmod17a%.so: $(objpfx)ld.so
++$(objpfx)tst-tlsmod17b.so: $(patsubst %,$(objpfx)tst-tlsmod17a%.so,$(tlsmod17a-suffixes))
++
+ CFLAGS-tst-align.c = $(stack-align-test-flags)
+ CFLAGS-tst-align2.c = $(stack-align-test-flags)
+ CFLAGS-tst-alignmod.c = $(stack-align-test-flags)
+--- libc/sysdeps/generic/dl-tls.c      12 May 2008 05:35:52 -0000      1.7
++++ libc/sysdeps/generic/dl-tls.c      16 Oct 2008 21:57:52 -0000      1.9
+@@ -637,7 +637,7 @@ __tls_get_addr (GET_ADDR_ARGS)
+                         newp = malloc ((2 + newsize) * sizeof (dtv_t));
+                         if (newp == NULL)
+                           oom ();
+-                        memcpy (newp, &dtv[-1], oldsize * sizeof (dtv_t));
++                        memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
+                       }
+                     else
+                       {
+--- libc/elf/tst-tls17.c       1 Jan 1970 00:00:00 -0000
++++ libc/elf/tst-tls17.c       17 Oct 2008 15:23:11 -0000      1.1
+@@ -0,0 +1,28 @@
++#include <dlfcn.h>
++#include <stdio.h>
++
++static int
++do_test (void)
++{
++  void *h = dlopen ("tst-tlsmod17b.so", RTLD_LAZY);
++  if (h == NULL)
++    {
++      puts ("unexpectedly failed to open tst-tlsmod17b.so");
++      exit (1);
++    }
++
++  int (*fp) (void) = (int (*) (void)) dlsym (h, "tlsmod17b");
++  if (fp == NULL)
++    {
++      puts ("cannot find tlsmod17b");
++      exit (1);
++    }
++
++  if (fp ())
++    exit (1);
++
++  return 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/elf/tst-tlsmod17a.c   1 Jan 1970 00:00:00 -0000
++++ libc/elf/tst-tlsmod17a.c   17 Oct 2008 15:23:44 -0000      1.1
+@@ -0,0 +1,23 @@
++#include <stdio.h>
++
++#ifndef N
++#define N 0
++#endif
++#define CONCAT1(s, n) s##n
++#define CONCAT(s, n) CONCAT1(s, n)
++
++__thread int CONCAT (v, N) = 4;
++
++int
++CONCAT (tlsmod17a, N) (void)
++{
++  int *p = &CONCAT (v, N);
++  /* GCC assumes &var is never NULL, add optimization barrier.  */
++  asm volatile ("" : "+r" (p));
++  if (p == NULL || *p != 4)
++    {
++      printf ("fail %d %p\n", N, p);
++      return 1;
++    }
++  return 0;
++}
+--- libc/elf/tst-tlsmod17b.c   1 Jan 1970 00:00:00 -0000
++++ libc/elf/tst-tlsmod17b.c   17 Oct 2008 15:23:44 -0000      1.1
+@@ -0,0 +1,15 @@
++#define P(N) extern int tlsmod17a##N (void);
++#define PS P(0) P(1) P(2) P(3) P(4) P(5) P(6) P(7) P(8) P(9) \
++         P(10) P(12) P(13) P(14) P(15) P(16) P(17) P(18) P(19)
++PS
++#undef P
++
++int
++tlsmod17b (void)
++{
++  int res = 0;
++#define P(N) res |= tlsmod17a##N ();
++  PS
++#undef P
++  return res;
++}
diff --git a/src/patches/glibc/glibc-rh470781.patch b/src/patches/glibc/glibc-rh470781.patch
new file mode 100644 (file)
index 0000000..faf4ffb
--- /dev/null
@@ -0,0 +1,23 @@
+2008-10-30  Ulrich Drepper  <drepper@redhat.com>
+
+       * grp/initgroups.c (internal_getgrouplist): Don't prematurely
+       abort if there is no initgroups_dyn function.
+
+--- libc/grp/initgroups.c      3 Aug 2006 15:39:47 -0000       1.37
++++ libc/grp/initgroups.c      30 Oct 2008 16:55:10 -0000      1.38
+@@ -94,13 +94,8 @@ internal_getgrouplist (const char *user,
+       fct = __nss_lookup_function (nip, "initgroups_dyn");
+       if (fct == NULL)
+-      {
+-        status = compat_call (nip, user, group, &start, size, groupsp,
+-                              limit, &errno);
+-
+-        if (nss_next_action (nip, NSS_STATUS_UNAVAIL) != NSS_ACTION_CONTINUE)
+-          break;
+-      }
++      status = compat_call (nip, user, group, &start, size, groupsp,
++                            limit, &errno);
+       else
+       status = DL_CALL_FCT (fct, (user, group, &start, size, groupsp,
+                                   limit, &errno));
diff --git a/src/patches/glibc/glibc-rtkaio-update.patch b/src/patches/glibc/glibc-rtkaio-update.patch
new file mode 100644 (file)
index 0000000..c3d1b38
--- /dev/null
@@ -0,0 +1,1735 @@
+2006-05-11  Jakub Jelinek  <jakub@redhat.com>
+
+       * Makefile (tests): Add tst-mqueue{8,9}, tst-timer5 and
+       tst-aiod{,64,2,3,4,5}.
+       (LDFLAGS-rtkaio.so): Add -Wl,--enable-new-dtags,-z,nodelete.
+       * sysdeps/unix/sysv/linux/kaio_misc.h: Include signal.h and
+       sysdep.h.
+       (aio_start_notify_thread, aio_create_helper_thread): Define
+       for !BROKEN_THREAD_SIGNALS.
+       (__aio_start_notify_thread, __aio_create_helper_thread): New
+       functions for !BROKEN_THREAD_SIGNALS.
+       * sysdeps/unix/sysv/linux/kaio_misc.c: Include sys/sysmacros.h.
+       (aio_create_helper_thread): Define if not yet defined.
+       (__aio_create_helper_thread): New function.
+       (__aio_wait_for_events): Pass 1 rather than 0 as min_nr to
+       io_getevents.
+       (handle_kernel_aio): Likewise.
+       (__aio_create_kernel_thread): Use aio_create_helper_thread.
+       (__aio_enqueue_user_request): Likewise.
+       (handle_fildes_io): Likewise.  Remove noreturn attribute,
+       return NULL instead of calling pthread_exit (NULL).
+       (__aio_enqueue_request_ctx): Call fcntl and fxstat64 to avoid using
+       kaio on non-O_DIRECT non-/dev/raw* filedescriptors.  For LIO_SYNC
+       and LIO_DSYNC also set kctx to KCTX_NONE.
+       * sysdeps/unix/sysv/linux/kaio_suspend.c (aio_suspend): Don't start
+       handle_kernel_aio thread if ktotal is zero.
+       * sysdeps/pthread/Makefile (tests): Add tst-mqueue8x.
+       (CFLAGS-tst-mqueue8x.c): Add -fexceptions.
+       * Versions.def (librtkaio): Add GLIBC_2.3.4 version.
+       * kaio_mq_close.c: New file.
+       * kaio_mq_getattr.c: New file.
+       * kaio_mq_notify.c: New file.
+       * kaio_mq_open.c: New file.
+       * kaio_mq_receive.c: New file.
+       * kaio_mq_send.c: New file.
+       * kaio_mq_setattr.c: New file.
+       * kaio_mq_timedreceive.c: New file.
+       * kaio_mq_timedsend.c: New file.
+       * kaio_mq_unlink.c: New file.
+       * sysdeps/pthread/tst-mqueue8x.c: New file.
+       * sysdeps/unix/sysv/linux/syscalls.list: New file.
+       * tst-mqueue8.c: New file.
+       * tst-mqueue9.c: New file.
+       * tst-timer5.c: New file.
+       * tst-aiod.h: New file.
+       * tst-aiod.c: New test.
+       * tst-aiod64.c: New test.
+       * tst-aiod2.c: New test.
+       * tst-aiod3.c: New test.
+       * tst-aiod4.c: New test.
+       * tst-aiod5.c: New test.
+       * sysdeps/mips/Makefile: New file.
+       * sysdeps/unix/alpha/Makefile: New file.
+       * sysdeps/unix/alpha/rtkaio-sysdep.S: New file.
+       * sysdeps/unix/mips/rtkaio-sysdep.S: New file.
+       * sysdeps/unix/sysv/linux/Makefile: New file.
+       * sysdeps/unix/sysv/linux/s390/Makefile: New file.
+       * sysdeps/unix/sysv/linux/s390/rtkaio-sysdep.S: New file.
+       * sysdeps/unix/sysv/linux/powerpc/Makefile: New file.
+       * sysdeps/unix/sysv/linux/powerpc/rtkaio-sysdep.c: New file.
+       * sysdeps/unix/sysv/linux/ia64/Makefile: New file.
+       * sysdeps/unix/sysv/linux/ia64/rtkaio-sysdep.S: New file.
+
+--- libc/rtkaio/Makefile.jj    2004-09-22 23:21:03.000000000 +0200
++++ libc/rtkaio/Makefile       2006-05-11 13:52:49.000000000 +0200
+@@ -1,4 +1,4 @@
+-# Copyright (C) 2003, 2004 Free Software Foundation, Inc.
++# Copyright (C) 2003, 2004, 2006 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
+@@ -42,7 +42,9 @@ librtkaio-routines = $(patsubst %,k%,$(a
+ tests := tst-shm tst-clock tst-clock_nanosleep tst-timer tst-timer2 \
+        tst-aio tst-aio64 tst-aio2 tst-aio3 tst-aio4 tst-aio5 tst-aio6 \
+        tst-aio7 tst-mqueue1 tst-mqueue2 tst-mqueue3 tst-mqueue4 \
+-       tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-timer3 tst-timer4
++       tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-mqueue8 tst-mqueue9 \
++       tst-timer3 tst-timer4 tst-timer5 \
++       tst-aiod tst-aiod64 tst-aiod2 tst-aiod3 tst-aiod4 tst-aiod5
+ extra-libs := librtkaio
+ extra-libs-others := $(extra-libs)
+@@ -61,7 +63,8 @@ CFLAGS-kaio_suspend.c = -fexceptions
+ CFLAGS-kaio_clock_nanosleep.c = -fexceptions -fasynchronous-unwind-tables
+ CFLAGS-kaio_librt-cancellation.c = -fasynchronous-unwind-tables
+-LDFLAGS-rtkaio.so = -Wl,-soname=lib$(libprefix)rt.so$(librt.so-version)
++LDFLAGS-rtkaio.so = -Wl,-soname=lib$(libprefix)rt.so$(librt.so-version) \
++                  -Wl,--enable-new-dtags,-z,nodelete
+ CPPFLAGS-librtkaio += -DIS_IN_librt=1
+ rpath-dirs := $(patsubst rt,rtkaio,$(rpath-dirs))
+--- libc/rtkaio/tst-aiod.h.jj  2006-05-11 13:00:06.000000000 +0200
++++ libc/rtkaio/tst-aiod.h     2006-05-11 13:01:45.000000000 +0200
+@@ -0,0 +1,52 @@
++/* Tests for AIO in librt.
++   Copyright (C) 1998, 2000, 2002, 2006 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
++
++   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 <fcntl.h>
++#include <sys/mman.h>
++#include <unistd.h>
++
++static int
++set_o_direct (int fd)
++{
++  int ret = -1;
++#ifdef O_DIRECT
++  if (fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) | O_DIRECT) >= 0)
++    {
++      int pgsz = sysconf (_SC_PAGESIZE);
++      char *buf = mmap (NULL, 16 * pgsz, PROT_READ | PROT_WRITE,
++                      MAP_PRIVATE | MAP_ANON, -1, 0);
++      if (buf != MAP_FAILED)
++      {
++        memset (buf, 0, 16 * pgsz);
++        for (int sz = 256; sz <= 16 * pgsz; sz *= 2)
++          if (write (fd, buf, sz) > 0)
++            {
++              ret = sz;
++              break;
++            }
++        ftruncate64 (fd, 0);
++        munmap (buf, 16 * pgsz);
++      }
++      if (ret < 0)
++      fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) & ~O_DIRECT);
++    }
++#endif
++  return ret;
++}
+--- libc/rtkaio/kaio_mq_send.c.jj      2006-05-10 15:23:59.000000000 +0200
++++ libc/rtkaio/kaio_mq_send.c 2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <mq_send.c>
+--- libc/rtkaio/sysdeps/unix/alpha/Makefile.jj 2006-05-11 11:40:39.000000000 +0200
++++ libc/rtkaio/sysdeps/unix/alpha/Makefile    2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1,3 @@
++ifeq ($(subdir),rtkaio)
++librtkaio-sysdep_routines += rtkaio-sysdep
++endif
+--- libc/rtkaio/sysdeps/unix/alpha/rtkaio-sysdep.S.jj  2006-05-11 11:40:39.000000000 +0200
++++ libc/rtkaio/sysdeps/unix/alpha/rtkaio-sysdep.S     2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <rt-sysdep.S>
+--- libc/rtkaio/sysdeps/unix/mips/rtkaio-sysdep.S.jj   2006-05-11 11:40:39.000000000 +0200
++++ libc/rtkaio/sysdeps/unix/mips/rtkaio-sysdep.S      2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <rt-sysdep.S>
+--- libc/rtkaio/sysdeps/unix/sysv/linux/Makefile.jj    2006-05-11 14:51:18.000000000 +0200
++++ libc/rtkaio/sysdeps/unix/sysv/linux/Makefile       2006-05-11 11:52:30.000000000 +0200
+@@ -0,0 +1,4 @@
++ifeq ($(subdir),rtkaio)
++CFLAGS-kaio_mq_send.c += -fexceptions
++CFLAGS-kaio_mq_receive.c += -fexceptions
++endif
+--- libc/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.h.jj 2004-09-22 23:21:05.000000000 +0200
++++ libc/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.h    2006-05-11 11:40:39.000000000 +0200
+@@ -1,4 +1,5 @@
+-/* Copyright (C) 1997,1999,2000,2001,2002,2003 Free Software Foundation, Inc.
++/* Copyright (C) 1997,1999,2000,2001,2002,2003,2006
++   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
+@@ -34,6 +35,9 @@
+ #include <aio.h>
+ #include <pthread.h>
+ #include <stdint.h>
++#include <signal.h>
++#include <sysdep.h>
++#include <limits.h>
+ typedef unsigned long kctx_t;
+ #define KCTX_NONE ~0UL
+@@ -212,5 +216,49 @@ extern int __aio_create_kernel_thread (v
+ extern int __have_no_kernel_aio attribute_hidden;
+ extern int __kernel_thread_started attribute_hidden;
++#ifndef BROKEN_THREAD_SIGNALS
++# define aio_start_notify_thread __aio_start_notify_thread
++# define aio_create_helper_thread __aio_create_helper_thread
++
++extern inline void
++__aio_start_notify_thread (void)
++{
++  sigset_t ss;
++  sigemptyset (&ss);
++  INTERNAL_SYSCALL_DECL (err);
++  INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8);
++}
++
++extern inline int
++__aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), void *arg)
++{
++  pthread_attr_t attr;
++
++  /* Make sure the thread is created detached.  */
++  pthread_attr_init (&attr);
++  pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
++
++  /* The helper thread needs only very little resources.  */
++  (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
++
++  /* Block all signals in the helper thread.  To do this thoroughly we
++     temporarily have to block all signals here.  */
++  sigset_t ss;
++  sigset_t oss;
++  sigfillset (&ss);
++  INTERNAL_SYSCALL_DECL (err);
++  INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, &oss, _NSIG / 8);
++
++  int ret = pthread_create (threadp, &attr, tf, arg);
++
++  /* Restore the signal mask.  */
++  INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL,
++                  _NSIG / 8);
++
++  (void) pthread_attr_destroy (&attr);
++  return ret;
++}                                                                                 
++#endif
++
+ #endif
+ #endif /* aio_misc.h */
+--- libc/rtkaio/sysdeps/unix/sysv/linux/s390/Makefile.jj       2006-05-11 11:40:39.000000000 +0200
++++ libc/rtkaio/sysdeps/unix/sysv/linux/s390/Makefile  2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1,3 @@
++ifeq ($(subdir),rtkaio)
++librtkaio-routines += rtkaio-sysdep
++endif
+--- libc/rtkaio/sysdeps/unix/sysv/linux/s390/rtkaio-sysdep.S.jj        2006-05-11 11:40:39.000000000 +0200
++++ libc/rtkaio/sysdeps/unix/sysv/linux/s390/rtkaio-sysdep.S   2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <rt-sysdep.S>
+--- libc/rtkaio/sysdeps/unix/sysv/linux/powerpc/Makefile.jj    2006-05-11 11:40:39.000000000 +0200
++++ libc/rtkaio/sysdeps/unix/sysv/linux/powerpc/Makefile       2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1,3 @@
++ifeq ($(subdir),rtkaio)
++librtkaio-routines += rtkaio-sysdep
++endif
+--- libc/rtkaio/sysdeps/unix/sysv/linux/powerpc/rtkaio-sysdep.c.jj     2006-05-11 11:40:39.000000000 +0200
++++ libc/rtkaio/sysdeps/unix/sysv/linux/powerpc/rtkaio-sysdep.c        2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <rt-sysdep.c>
+--- libc/rtkaio/sysdeps/unix/sysv/linux/kaio_suspend.c.jj      2004-09-22 23:21:05.000000000 +0200
++++ libc/rtkaio/sysdeps/unix/sysv/linux/kaio_suspend.c 2006-05-11 14:49:47.000000000 +0200
+@@ -1,5 +1,6 @@
+ /* Suspend until termination of a requests.
+-   Copyright (C) 1997,1998,1999,2000,2002,2003 Free Software Foundation, Inc.
++   Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2006
++   Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+@@ -150,7 +151,7 @@ aio_suspend (list, nent, timeout)
+       pthread_cleanup_push (cleanup, &clparam);
+-      if (!__kernel_thread_started)
++      if (!__kernel_thread_started && ktotal)
+       {
+         /* If the kernel aio thread was not started yet all requests
+            are served by the kernel and there are no other threads running,
+--- libc/rtkaio/sysdeps/unix/sysv/linux/ia64/Makefile.jj       2006-05-11 11:40:39.000000000 +0200
++++ libc/rtkaio/sysdeps/unix/sysv/linux/ia64/Makefile  2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1,3 @@
++ifeq ($(subdir),rtkaio)
++librtkaio-routines += rtkaio-sysdep
++endif
+--- libc/rtkaio/sysdeps/unix/sysv/linux/ia64/rtkaio-sysdep.S.jj        2006-05-11 11:40:39.000000000 +0200
++++ libc/rtkaio/sysdeps/unix/sysv/linux/ia64/rtkaio-sysdep.S   2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <rt-sysdep.S>
+--- libc/rtkaio/sysdeps/unix/sysv/linux/syscalls.list.jj       2006-05-10 16:22:10.000000000 +0200
++++ libc/rtkaio/sysdeps/unix/sysv/linux/syscalls.list  2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1,5 @@
++# File name           Caller  Syscall name    Args            Strong name             Weak names
++
++kaio_mq_timedsend     -       mq_timedsend    Ci:ipiip        __GI_mq_timedsend       mq_timedsend
++kaio_mq_timedreceive  -       mq_timedreceive Ci:ipipp        __GI_mq_timedreceive    mq_timedreceive
++kaio_mq_setattr               -       mq_getsetattr   i:ipp           __GI_mq_setattr         mq_setattr
+--- libc/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c.jj 2004-09-22 23:21:05.000000000 +0200
++++ libc/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c    2006-05-11 14:38:41.000000000 +0200
+@@ -1,5 +1,5 @@
+ /* Handle general operations.
+-   Copyright (C) 1997,1998,1999,2000,2001,2002,2003
++   Copyright (C) 1997,1998,1999,2000,2001,2002,2003,2006
+    Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+@@ -34,6 +34,28 @@
+ #include <unistd.h>
+ #include <sys/stat.h>
+ #include <sys/time.h>
++#include <sys/sysmacros.h>
++
++#ifndef aio_create_helper_thread
++# define aio_create_helper_thread __aio_create_helper_thread
++
++extern inline int
++__aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), void *arg)
++{
++  pthread_attr_t attr;
++
++  /* Make sure the thread is created detached.  */
++  pthread_attr_init (&attr);
++  pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
++
++  int ret = pthread_create (threadp, &attr, tf, arg);
++
++  (void) pthread_attr_destroy (&attr);
++  return ret;
++}
++
++#endif
++
+ static void add_request_to_runlist (struct requestlist *newrequest)
+       internal_function;
+@@ -421,7 +443,7 @@ __aio_wait_for_events (kctx_t kctx, cons
+   ts.tv_nsec = 0;
+   do
+     {
+-      ret = INTERNAL_SYSCALL (io_getevents, err, 5, kctx, 0, 10, ev,
++      ret = INTERNAL_SYSCALL (io_getevents, err, 5, kctx, 1, 10, ev,
+                             timespec);
+       if (INTERNAL_SYSCALL_ERROR_P (ret, err) || ret == 0)
+       break;
+@@ -453,16 +475,11 @@ internal_function
+ __aio_create_kernel_thread (void)
+ {
+   pthread_t thid;
+-  pthread_attr_t attr;
+   if (__kernel_thread_started)
+     return 0;
+-  /* Make sure the thread is created detached.  */
+-  pthread_attr_init (&attr);
+-  pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+-
+-  if (pthread_create (&thid, &attr, handle_kernel_aio, NULL) != 0)
++  if (aio_create_helper_thread (&thid, handle_kernel_aio, NULL) != 0)
+     return -1;
+   __kernel_thread_started = 1;
+   return 0;
+@@ -477,7 +494,7 @@ handle_kernel_aio (void *arg __attribute
+   for (;;)
+     {
+-      ret = INTERNAL_SYSCALL (io_getevents, err, 5, __aio_kioctx, 0, 10, ev,
++      ret = INTERNAL_SYSCALL (io_getevents, err, 5, __aio_kioctx, 1, 10, ev,
+                             NULL);
+       if (INTERNAL_SYSCALL_ERROR_P (ret, err) || ret == 0)
+         continue;
+@@ -593,16 +610,11 @@ __aio_enqueue_user_request (struct reque
+       if (nthreads < optim.aio_threads && idle_thread_count == 0)
+       {
+         pthread_t thid;
+-        pthread_attr_t attr;
+-
+-        /* Make sure the thread is created detached.  */
+-        pthread_attr_init (&attr);
+-        pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+         running = newp->running = allocated;
+         /* Now try to start a thread.  */
+-        if (pthread_create (&thid, &attr, handle_fildes_io, newp) == 0)
++        if (aio_create_helper_thread (&thid, handle_fildes_io, newp) == 0)
+           /* We managed to enqueue the request.  All errors which can
+              happen now can be recognized by calls to `aio_return' and
+              `aio_error'.  */
+@@ -653,6 +665,7 @@ __aio_enqueue_request_ctx (aiocb_union *
+       aiocbp->aiocb.aio_reqprio = 0;
+       /* FIXME: Kernel doesn't support sync yet.  */
+       operation &= ~LIO_KTHREAD;
++      kctx = KCTX_NONE;
+     }
+   else if (aiocbp->aiocb.aio_reqprio < 0
+          || aiocbp->aiocb.aio_reqprio > AIO_PRIO_DELTA_MAX)
+@@ -664,6 +677,23 @@ __aio_enqueue_request_ctx (aiocb_union *
+       return NULL;
+     }
++  if ((operation & LIO_KTHREAD) || kctx != KCTX_NONE)
++    {
++      /* io_* is only really asynchronous for O_DIRECT or /dev/raw*.  */
++      int fl = __fcntl (aiocbp->aiocb.aio_fildes, F_GETFL);
++      if (fl < 0 || (fl & O_DIRECT) == 0)
++      {
++        struct stat64 st;
++        if (__fxstat64 (_STAT_VER, aiocbp->aiocb.aio_fildes, &st) < 0
++            || ! S_ISCHR (st.st_mode)
++            || major (st.st_rdev) != 162)
++          {
++            operation &= ~LIO_KTHREAD;
++            kctx = KCTX_NONE;
++          }
++      }
++    }
++
+   /* Compute priority for this request.  */
+   pthread_getschedparam (pthread_self (), &policy, &param);
+   prio = param.sched_priority - aiocbp->aiocb.aio_reqprio;
+@@ -832,7 +862,6 @@ wait_for_kernel_requests (int fildes)
+ static void *
+-__attribute__ ((noreturn))
+ handle_fildes_io (void *arg)
+ {
+   pthread_t self = pthread_self ();
+@@ -1026,16 +1055,11 @@ handle_fildes_io (void *arg)
+             else if (nthreads < optim.aio_threads)
+               {
+                 pthread_t thid;
+-                pthread_attr_t attr;
+-
+-                /* Make sure the thread is created detached.  */
+-                pthread_attr_init (&attr);
+-                pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+                 /* Now try to start a thread. If we fail, no big deal,
+                    because we know that there is at least one thread (us)
+                    that is working on AIO operations. */
+-                if (pthread_create (&thid, &attr, handle_fildes_io, NULL)
++                if (aio_create_helper_thread (&thid, handle_fildes_io, NULL)
+                     == 0)
+                   ++nthreads;
+               }
+@@ -1047,7 +1071,7 @@ handle_fildes_io (void *arg)
+     }
+   while (runp != NULL);
+-  pthread_exit (NULL);
++  return NULL;
+ }
+--- libc/rtkaio/sysdeps/pthread/Makefile.jj    2004-09-22 23:21:05.000000000 +0200
++++ libc/rtkaio/sysdeps/pthread/Makefile       2006-05-11 11:40:39.000000000 +0200
+@@ -14,6 +14,11 @@ $(objpfx)tst-timer: $(objpfx)librtkaio.s
+ else
+ $(objpfx)tst-timer: $(objpfx)librtkaio.a $(static-thread-library)
+ endif
++
++ifeq ($(have-forced-unwind),yes)
++tests += tst-mqueue8x
++CFLAGS-tst-mqueue8x.c += -fexceptions
++endif
+ endif
+ endif
+--- libc/rtkaio/sysdeps/pthread/tst-mqueue8x.c.jj      2006-05-10 14:34:34.000000000 +0200
++++ libc/rtkaio/sysdeps/pthread/tst-mqueue8x.c 2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include_next <tst-mqueue8x.c>
+--- libc/rtkaio/sysdeps/mips/Makefile.jj       2006-05-11 11:40:39.000000000 +0200
++++ libc/rtkaio/sysdeps/mips/Makefile  2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1,3 @@
++ifeq ($(subdir),rtkaio)
++librtkaio-sysdep_routines += rtkaio-sysdep
++endif
+--- libc/rtkaio/kaio_mq_close.c.jj     2006-05-10 15:23:59.000000000 +0200
++++ libc/rtkaio/kaio_mq_close.c        2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <mq_close.c>
+--- libc/rtkaio/tst-mqueue9.c.jj       2006-05-10 14:27:13.000000000 +0200
++++ libc/rtkaio/tst-mqueue9.c  2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <rt/tst-mqueue9.c>
+--- libc/rtkaio/kaio_mq_timedsend.c.jj 2006-05-10 15:23:59.000000000 +0200
++++ libc/rtkaio/kaio_mq_timedsend.c    2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <mq_timedsend.c>
+--- libc/rtkaio/kaio_mq_getattr.c.jj   2006-05-10 15:23:59.000000000 +0200
++++ libc/rtkaio/kaio_mq_getattr.c      2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <mq_getattr.c>
+--- libc/rtkaio/kaio_mq_setattr.c.jj   2006-05-10 15:23:59.000000000 +0200
++++ libc/rtkaio/kaio_mq_setattr.c      2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <mq_setattr.c>
+--- libc/rtkaio/tst-timer5.c.jj        2006-05-10 14:27:56.000000000 +0200
++++ libc/rtkaio/tst-timer5.c   2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <rt/tst-timer5.c>
+--- libc/rtkaio/Versions.def.jj        2004-09-22 23:21:03.000000000 +0200
++++ libc/rtkaio/Versions.def   2006-05-11 11:40:39.000000000 +0200
+@@ -3,4 +3,5 @@ librtkaio {
+   GLIBC_2.2
+   GLIBC_2.3
+   GLIBC_2.3.3
++  GLIBC_2.3.4
+ }
+--- libc/rtkaio/kaio_mq_open.c.jj      2006-05-10 15:23:59.000000000 +0200
++++ libc/rtkaio/kaio_mq_open.c 2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <mq_open.c>
+--- libc/rtkaio/kaio_mq_receive.c.jj   2006-05-10 15:23:59.000000000 +0200
++++ libc/rtkaio/kaio_mq_receive.c      2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <mq_receive.c>
+--- libc/rtkaio/kaio_mq_unlink.c.jj    2006-05-10 15:23:59.000000000 +0200
++++ libc/rtkaio/kaio_mq_unlink.c       2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <mq_unlink.c>
+--- libc/rtkaio/tst-aiod3.c.jj 2006-05-11 13:31:34.000000000 +0200
++++ libc/rtkaio/tst-aiod3.c    2006-05-11 13:55:44.000000000 +0200
+@@ -0,0 +1,118 @@
++/* Test for notification mechanism in lio_listio.
++   Copyright (C) 2000, 2002, 2006 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 <aio.h>
++#include <signal.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <errno.h>
++#include "tst-aiod.h"
++
++int flag;
++
++
++static void
++thrfct (sigval_t arg)
++{
++  flag = 1;
++}
++
++
++static int
++do_test (int argc, char *argv[])
++{
++  char name[] = "/tmp/aio3.XXXXXX";
++  int fd;
++  struct aiocb *arr[1];
++  struct aiocb cb;
++  static const char buf[] = "Hello World\n";
++
++  fd = mkstemp (name);
++  if (fd == -1)
++    {
++      printf ("cannot open temp name: %m\n");
++      return 1;
++    }
++
++  unlink (name);
++
++  arr[0] = &cb;
++
++  void *p;
++  int sz = set_o_direct (fd);
++  if (sz != -1)
++    {
++      int err = posix_memalign (&p, sz, sz);
++      if (err)
++      {
++        errno = err;
++        printf ("cannot allocate memory: %m\n");
++        return 1;
++      }
++      memcpy (p, buf, sizeof (buf) - 1);
++      memset (p + sizeof (buf) - 1, ' ', sz - sizeof (buf) + 1);
++      printf ("Using O_DIRECT with block size %d\n", sz);
++    }
++  else
++    {
++      p = (void *) buf;
++      sz = sizeof (buf) - 1;
++    }
++
++  cb.aio_fildes = fd;
++  cb.aio_lio_opcode = LIO_WRITE;
++  cb.aio_reqprio = 0;
++  cb.aio_buf = p;
++  cb.aio_nbytes = sz;
++  cb.aio_offset = 0;
++  cb.aio_sigevent.sigev_notify = SIGEV_THREAD;
++  cb.aio_sigevent.sigev_notify_function = thrfct;
++  cb.aio_sigevent.sigev_notify_attributes = NULL;
++  cb.aio_sigevent.sigev_value.sival_ptr = NULL;
++
++  if (lio_listio (LIO_NOWAIT, arr, 1, NULL) < 0)
++    {
++      if (errno == ENOSYS)
++      {
++        puts ("no aio support in this configuration");
++        return 0;
++      }
++      printf ("lio_listio failed: %m\n");
++      return 1;
++    }
++
++  if (aio_suspend ((const struct aiocb *const *) arr, 1, NULL) < 0)
++    {
++      printf ("aio_suspend failed: %m\n");
++      return 1;
++    }
++
++  if (flag != 0)
++    {
++      puts ("thread created, should not have happened");
++      return 1;
++    }
++
++  puts ("all OK");
++
++  return 0;
++}
++
++#include "../test-skeleton.c"
+--- libc/rtkaio/tst-aiod.c.jj  2006-05-11 11:56:20.000000000 +0200
++++ libc/rtkaio/tst-aiod.c     2006-05-11 13:55:20.000000000 +0200
+@@ -0,0 +1,307 @@
++/* Tests for AIO in librt.
++   Copyright (C) 1998, 2000, 2002, 2006 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
++
++   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 <aio.h>
++#include <errno.h>
++#include <error.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/stat.h>
++#include "tst-aiod.h"
++
++
++/* Prototype for our test function.  */
++extern void do_prepare (int argc, char *argv[]);
++extern int do_test (int argc, char *argv[]);
++
++/* We have a preparation function.  */
++#define PREPARE do_prepare
++
++/* We might need a bit longer timeout.  */
++#define TIMEOUT 20 /* sec */
++
++/* This defines the `main' function and some more.  */
++#include <test-skeleton.c>
++
++
++/* These are for the temporary file we generate.  */
++char *name;
++int fd;
++char *tmpbuf;
++int blksz = 100;
++
++void
++do_prepare (int argc, char *argv[])
++{
++  char name_len;
++
++  name_len = strlen (test_dir);
++  name = malloc (name_len + sizeof ("/aioXXXXXX"));
++  mempcpy (mempcpy (name, test_dir, name_len),
++         "/aioXXXXXX", sizeof ("/aioXXXXXX"));
++  add_temp_file (name);
++
++  /* Open our test file.   */
++  fd = mkstemp (name);
++  if (fd == -1)
++    error (EXIT_FAILURE, errno, "cannot open test file `%s'", name);
++
++  int sz = set_o_direct (fd);
++  if (sz != -1)
++    {
++      blksz = sz;
++      printf ("Using O_DIRECT with block size %d\n", blksz);
++    }
++}
++
++
++static int
++test_file (const void *buf, size_t size, int fd, const char *msg)
++{
++  struct stat st;
++  char *tmp = tmpbuf;
++
++  errno = 0;
++  if (fstat (fd, &st) < 0)
++    {
++      error (0, errno, "%s: failed stat", msg);
++      return 1;
++    }
++
++  if (st.st_size != (off_t) size)
++    {
++      error (0, errno, "%s: wrong size: %lu, should be %lu",
++           msg, (unsigned long int) st.st_size, (unsigned long int) size);
++      return 1;
++    }
++
++  if (pread (fd, tmp, size, 0) != (ssize_t) size)
++    {
++      error (0, errno, "%s: failed pread", msg);
++      return 1;
++    }
++
++  if (memcmp (buf, tmp, size) != 0)
++    {
++      error (0, errno, "%s: failed comparison", msg);
++      return 1;
++    }
++
++  printf ("%s test ok\n", msg);
++
++  return 0;
++}
++
++
++static int
++do_wait (struct aiocb **cbp, size_t nent, int allowed_err)
++{
++  int go_on;
++  size_t cnt;
++  int result = 0;
++
++  do
++    {
++      aio_suspend ((const struct aiocb *const *) cbp, nent, NULL);
++      go_on = 0;
++      for (cnt = 0; cnt < nent; ++cnt)
++      if (cbp[cnt] != NULL)
++        {
++          if (aio_error (cbp[cnt]) == EINPROGRESS)
++            go_on = 1;
++          else
++            {
++              if (aio_return (cbp[cnt]) == -1
++                  && (allowed_err == 0
++                      || aio_error (cbp[cnt]) != allowed_err))
++                {
++                  error (0, aio_error (cbp[cnt]), "Operation failed\n");
++                  result = 1;
++                }
++              cbp[cnt] = NULL;
++            }
++        }
++    }
++  while (go_on);
++
++  return result;
++}
++
++
++int
++do_test (int argc, char *argv[])
++{
++  struct aiocb cbs[10];
++  struct aiocb cbs_fsync;
++  struct aiocb *cbp[10];
++  struct aiocb *cbp_fsync[1];
++  char *buf;
++  size_t cnt;
++  int result = 0;
++
++  buf = mmap (NULL, 20 * blksz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
++  tmpbuf = buf + 10 * blksz;
++  if (buf == MAP_FAILED)
++    {
++      error (0, errno, "mmap failed");
++      return 1;
++    }
++
++  /* Preparation.  */
++  for (cnt = 0; cnt < 10; ++cnt)
++    {
++      cbs[cnt].aio_fildes = fd;
++      cbs[cnt].aio_reqprio = 0;
++      cbs[cnt].aio_buf = memset (&buf[cnt * blksz], '0' + cnt, blksz);
++      cbs[cnt].aio_nbytes = blksz;
++      cbs[cnt].aio_offset = cnt * blksz;
++      cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE;
++
++      cbp[cnt] = &cbs[cnt];
++    }
++
++  /* First a simple test.  */
++  for (cnt = 10; cnt > 0; )
++    if (aio_write (cbp[--cnt]) < 0 && errno == ENOSYS)
++      {
++      error (0, 0, "no aio support in this configuration");
++      return 0;
++      }
++  /* Wait 'til the results are there.  */
++  result |= do_wait (cbp, 10, 0);
++  /* Test this.  */
++  result |= test_file (buf, 10 * blksz, fd, "aio_write");
++
++  /* Read now as we've written it.  */
++  memset (buf, '\0', 10 * blksz);
++  /* Issue the commands.  */
++  for (cnt = 10; cnt > 0; )
++    {
++      --cnt;
++      cbp[cnt] = &cbs[cnt];
++      aio_read (cbp[cnt]);
++    }
++  /* Wait 'til the results are there.  */
++  result |= do_wait (cbp, 10, 0);
++  /* Test this.  */
++  for (cnt = 0; cnt < 10 * blksz; ++cnt)
++    if (buf[cnt] != '0' + (cnt / blksz))
++      {
++      result = 1;
++      error (0, 0, "comparison failed for aio_read test");
++      break;
++      }
++
++  if (cnt == 10 * blksz)
++    puts ("aio_read test ok");
++
++  /* Remove the test file contents.  */
++  if (ftruncate (fd, 0) < 0)
++    {
++      error (0, errno, "ftruncate failed\n");
++      result = 1;
++    }
++
++  /* Test lio_listio.  */
++  for (cnt = 0; cnt < 10; ++cnt)
++    {
++      cbs[cnt].aio_lio_opcode = LIO_WRITE;
++      cbp[cnt] = &cbs[cnt];
++    }
++  /* Issue the command.  */
++  lio_listio (LIO_WAIT, cbp, 10, NULL);
++  /* ...and immediately test it since we started it in wait mode.  */
++  result |= test_file (buf, 10 * blksz, fd, "lio_listio (write)");
++
++  /* Test aio_fsync.  */
++  cbs_fsync.aio_fildes = fd;
++  cbs_fsync.aio_sigevent.sigev_notify = SIGEV_NONE;
++  cbp_fsync[0] = &cbs_fsync;
++
++  /* Remove the test file contents first.  */
++  if (ftruncate (fd, 0) < 0)
++    {
++      error (0, errno, "ftruncate failed\n");
++      result = 1;
++    }
++
++  /* Write again.  */
++  for (cnt = 10; cnt > 0; )
++    aio_write (cbp[--cnt]);
++
++  if (aio_fsync (O_SYNC, &cbs_fsync) < 0)
++    {
++      error (0, errno, "aio_fsync failed\n");
++      result = 1;
++    }
++  result |= do_wait (cbp_fsync, 1, 0);
++
++  /* ...and test since all data should be on disk now.  */
++  result |= test_file (buf, 10 * blksz, fd, "aio_fsync (aio_write)");
++
++  /* Test aio_cancel.  */
++  /* Remove the test file contents first.  */
++  if (ftruncate (fd, 0) < 0)
++    {
++      error (0, errno, "ftruncate failed\n");
++      result = 1;
++    }
++
++  /* Write again.  */
++  for (cnt = 10; cnt > 0; )
++    aio_write (cbp[--cnt]);
++
++  /* Cancel all requests.  */
++  if (aio_cancel (fd, NULL) == -1)
++    printf ("aio_cancel (fd, NULL) cannot cancel anything\n");
++
++  result |= do_wait (cbp, 10, ECANCELED);
++
++  /* Another test for aio_cancel.  */
++  /* Remove the test file contents first.  */
++  if (ftruncate (fd, 0) < 0)
++    {
++      error (0, errno, "ftruncate failed\n");
++      result = 1;
++    }
++
++  /* Write again.  */
++  for (cnt = 10; cnt > 0; )
++    {
++      --cnt;
++      cbp[cnt] = &cbs[cnt];
++      aio_write (cbp[cnt]);
++    }
++  puts ("finished3");
++
++  /* Cancel all requests.  */
++  for (cnt = 10; cnt > 0; )
++    if (aio_cancel (fd, cbp[--cnt]) == -1)
++      /* This is not an error.  The request can simply be finished.  */
++      printf ("aio_cancel (fd, cbp[%Zd]) cannot be canceled\n", cnt);
++  puts ("finished2");
++
++  result |= do_wait (cbp, 10, ECANCELED);
++
++  puts ("finished");
++
++  return result;
++}
+--- libc/rtkaio/kaio_mq_timedreceive.c.jj      2006-05-10 15:23:59.000000000 +0200
++++ libc/rtkaio/kaio_mq_timedreceive.c 2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <mq_timedreceive.c>
+--- libc/rtkaio/tst-aiod4.c.jj 2006-05-11 13:31:34.000000000 +0200
++++ libc/rtkaio/tst-aiod4.c    2006-05-11 13:55:52.000000000 +0200
+@@ -0,0 +1,182 @@
++/* Test for completion signal handling.
++   Copyright (C) 2000, 2001, 2002, 2006 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 <aio.h>
++#include <signal.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <errno.h>
++#include "tst-aiod.h"
++
++/* We might need a bit longer timeout.  */
++#define TIMEOUT 10 /* sec */
++
++int my_signo;
++
++volatile sig_atomic_t flag;
++
++
++static void
++sighandler (const int signo)
++{
++  flag = signo;
++}
++
++static int
++wait_flag (void)
++{
++  while (flag == 0)
++    {
++      puts ("Sleeping...");
++      sleep (1);
++    }
++
++  if (flag != my_signo)
++    {
++      printf ("signal handler received wrong signal, flag is %d\n", flag);
++      return 1;
++    }
++
++  return 0;
++}
++
++#ifndef SIGRTMIN
++# define SIGRTMIN -1
++# define SIGRTMAX -1
++#endif
++
++static int
++do_test (int argc, char *argv[])
++{
++  char name[] = "/tmp/aio4.XXXXXX";
++  int fd;
++  struct aiocb *arr[1];
++  struct aiocb cb;
++  static const char buf[] = "Hello World\n";
++  struct aioinit init = {10, 20, 0};
++  struct sigaction sa;
++  struct sigevent ev;
++
++  if (SIGRTMIN == -1)
++  {
++      printf ("RT signals not supported.\n");
++      return 0;
++  }
++
++  /* Select a signal from the middle of the available choices... */
++  my_signo = (SIGRTMAX + SIGRTMIN) / 2;
++
++  fd = mkstemp (name);
++  if (fd == -1)
++    {
++      printf ("cannot open temp name: %m\n");
++      return 1;
++    }
++
++  unlink (name);
++
++  /* Test also aio_init.  */
++  aio_init (&init);
++
++  arr[0] = &cb;
++
++  void *p;
++  int sz = set_o_direct (fd);
++  if (sz != -1)
++    {
++      int err = posix_memalign (&p, sz, sz);
++      if (err)
++      {
++        errno = err;
++        printf ("cannot allocate memory: %m\n");
++        return 1;
++      }
++      memcpy (p, buf, sizeof (buf) - 1);
++      memset (p + sizeof (buf) - 1, ' ', sz - sizeof (buf) + 1);
++      printf ("Using O_DIRECT with block size %d\n", sz);
++    }
++  else
++    {
++      p = (void *) buf;
++      sz = sizeof (buf) - 1;
++    }
++
++  cb.aio_fildes = fd;
++  cb.aio_lio_opcode = LIO_WRITE;
++  cb.aio_reqprio = 0;
++  cb.aio_buf = p;
++  cb.aio_nbytes = sz;
++  cb.aio_offset = 0;
++  cb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
++  cb.aio_sigevent.sigev_notify_function = NULL;
++  cb.aio_sigevent.sigev_notify_attributes = NULL;
++  cb.aio_sigevent.sigev_signo = my_signo;
++  cb.aio_sigevent.sigev_value.sival_ptr = NULL;
++
++  ev.sigev_notify = SIGEV_SIGNAL;
++  ev.sigev_notify_function = NULL;
++  ev.sigev_notify_attributes = NULL;
++  ev.sigev_signo = my_signo;
++
++  sa.sa_handler = sighandler;
++  sigemptyset (&sa.sa_mask);
++  sa.sa_flags = SA_RESTART;
++
++  if (sigaction (my_signo, &sa, NULL) < 0)
++    {
++      printf ("sigaction failed: %m\n");
++      return 1;
++    }
++
++  flag = 0;
++  /* First use aio_write.  */
++  if (aio_write (arr[0]) < 0)
++    {
++      if (errno == ENOSYS)
++      {
++        puts ("no aio support in this configuration");
++        return 0;
++      }
++      printf ("aio_write failed: %m\n");
++      return 1;
++    }
++
++  if (wait_flag ())
++    return 1;
++
++  puts ("aio_write OK");
++
++  flag = 0;
++  /* Again with lio_listio.  */
++  if (lio_listio (LIO_NOWAIT, arr, 1, &ev) < 0)
++    {
++      printf ("lio_listio failed: %m\n");
++      return 1;
++    }
++
++  if (wait_flag ())
++    return 1;
++
++  puts ("all OK");
++
++  return 0;
++}
++
++#include "../test-skeleton.c"
+--- libc/rtkaio/kaio_mq_notify.c.jj    2006-05-10 15:23:59.000000000 +0200
++++ libc/rtkaio/kaio_mq_notify.c       2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <mq_notify.c>
+--- libc/rtkaio/tst-aiod5.c.jj 2006-05-11 13:31:34.000000000 +0200
++++ libc/rtkaio/tst-aiod5.c    2006-05-11 13:57:23.000000000 +0200
+@@ -0,0 +1,152 @@
++/* Test for completion thread handling.
++   Copyright (C) 2000, 2002, 2006 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 <aio.h>
++#include <signal.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <errno.h>
++#include "tst-aiod.h"
++
++/* We might need a bit longer timeout.  */
++#define TIMEOUT 10 /* sec */
++
++#define MY_SIVAL 27
++
++volatile sig_atomic_t flag;
++
++
++static void
++callback (sigval_t s)
++{
++  flag = s.sival_int;
++}
++
++static int
++wait_flag (void)
++{
++  while (flag == 0)
++    {
++      puts ("Sleeping...");
++      sleep (1);
++    }
++
++  if (flag != MY_SIVAL)
++    {
++      printf ("signal handler received wrong signal, flag is %d\n", flag);
++      return 1;
++    }
++
++  return 0;
++}
++
++
++static int
++do_test (int argc, char *argv[])
++{
++  char name[] = "/tmp/aio5.XXXXXX";
++  int fd;
++  struct aiocb *arr[1];
++  struct aiocb cb;
++  static const char buf[] = "Hello World\n";
++  struct sigevent ev;
++
++  fd = mkstemp (name);
++  if (fd == -1)
++    {
++      printf ("cannot open temp name: %m\n");
++      return 1;
++    }
++
++  unlink (name);
++
++  arr[0] = &cb;
++
++  void *p;
++  int sz = set_o_direct (fd);
++  if (sz != -1)
++    {
++      int err = posix_memalign (&p, sz, sz);
++      if (err)
++      {
++        errno = err;
++        printf ("cannot allocate memory: %m\n");
++        return 1;
++      }
++      memcpy (p, buf, sizeof (buf) - 1);
++      memset (p + sizeof (buf) - 1, ' ', sz - sizeof (buf) + 1);
++      printf ("Using O_DIRECT with block size %d\n", sz);
++    }
++  else
++    {
++      p = (void *) buf;
++      sz = sizeof (buf) - 1;
++    }
++
++  cb.aio_fildes = fd;
++  cb.aio_lio_opcode = LIO_WRITE;
++  cb.aio_reqprio = 0;
++  cb.aio_buf = p;
++  cb.aio_nbytes = sz;
++  cb.aio_offset = 0;
++  cb.aio_sigevent.sigev_notify = SIGEV_THREAD;
++  cb.aio_sigevent.sigev_notify_function = callback;
++  cb.aio_sigevent.sigev_notify_attributes = NULL;
++  cb.aio_sigevent.sigev_value.sival_int = MY_SIVAL;
++
++  ev.sigev_notify = SIGEV_THREAD;
++  ev.sigev_notify_function = callback;
++  ev.sigev_notify_attributes = NULL;
++  ev.sigev_value.sival_int = MY_SIVAL;
++
++  /* First use aio_write.  */
++  if (aio_write (arr[0]) < 0)
++    {
++      if (errno == ENOSYS)
++      {
++        puts ("no aio support in this configuration");
++        return 0;
++      }
++      printf ("aio_write failed: %m\n");
++      return 1;
++    }
++
++  if (wait_flag ())
++    return 1;
++
++  puts ("aio_write OK");
++
++  flag = 0;
++  /* Again with lio_listio.  */
++  if (lio_listio (LIO_NOWAIT, arr, 1, &ev) < 0)
++    {
++      printf ("lio_listio failed: %m\n");
++      return 1;
++    }
++
++  if (wait_flag ())
++    return 1;
++
++  puts ("all OK");
++
++  return 0;
++}
++
++#include "../test-skeleton.c"
+--- libc/rtkaio/tst-aiod2.c.jj 2006-05-11 13:31:34.000000000 +0200
++++ libc/rtkaio/tst-aiod2.c    2006-05-11 13:55:34.000000000 +0200
+@@ -0,0 +1,113 @@
++/* Test for notification mechanism in lio_listio.
++   Copyright (C) 2000, 2002, 2006 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
++
++   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 <aio.h>
++#include <signal.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <errno.h>
++#include "tst-aiod.h"
++
++int flag;
++
++
++static void
++thrfct (sigval_t arg)
++{
++  flag = 1;
++}
++
++
++static int
++do_test (int argc, char *argv[])
++{
++  char name[] = "/tmp/aio2.XXXXXX";
++  int fd;
++  struct aiocb *arr[1];
++  struct aiocb cb;
++  static const char buf[] = "Hello World\n";
++
++  fd = mkstemp (name);
++  if (fd == -1)
++    {
++      printf ("cannot open temp name: %m\n");
++      return 1;
++    }
++
++  unlink (name);
++
++  arr[0] = &cb;
++
++  void *p;
++  int sz = set_o_direct (fd);
++  if (sz != -1)
++    {
++      int err = posix_memalign (&p, sz, sz);
++      if (err)
++      {
++        errno = err;
++        printf ("cannot allocate memory: %m\n");
++        return 1;
++      }
++      memcpy (p, buf, sizeof (buf) - 1);
++      memset (p + sizeof (buf) - 1, ' ', sz - sizeof (buf) + 1);
++      printf ("Using O_DIRECT with block size %d\n", sz);
++    }
++  else
++    {
++      p = (void *) buf;
++      sz = sizeof (buf) - 1;
++    }
++
++  cb.aio_fildes = fd;
++  cb.aio_lio_opcode = LIO_WRITE;
++  cb.aio_reqprio = 0;
++  cb.aio_buf = p;
++  cb.aio_nbytes = sz;
++  cb.aio_offset = 0;
++  cb.aio_sigevent.sigev_notify = SIGEV_THREAD;
++  cb.aio_sigevent.sigev_notify_function = thrfct;
++  cb.aio_sigevent.sigev_notify_attributes = NULL;
++  cb.aio_sigevent.sigev_value.sival_ptr = NULL;
++
++  if (lio_listio (LIO_WAIT, arr, 1, NULL) < 0)
++    {
++      if (errno == ENOSYS)
++      {
++        puts ("no aio support in this configuration");
++        return 0;
++      }
++      printf ("lio_listio failed: %m\n");
++      return 1;
++    }
++
++  if (flag != 0)
++    {
++      puts ("thread created, should not have happened");
++      return 1;
++    }
++
++  puts ("all OK");
++
++  return 0;
++}
++
++#include "../test-skeleton.c"
+--- libc/rtkaio/tst-mqueue8.c.jj       2006-05-10 14:27:13.000000000 +0200
++++ libc/rtkaio/tst-mqueue8.c  2006-05-11 11:40:39.000000000 +0200
+@@ -0,0 +1 @@
++#include <rt/tst-mqueue8.c>
+--- libc/rtkaio/tst-aiod64.c.jj        2006-05-11 13:31:34.000000000 +0200
++++ libc/rtkaio/tst-aiod64.c   2006-05-11 13:55:27.000000000 +0200
+@@ -0,0 +1,308 @@
++/* Tests for 64bit AIO in librt.
++   Copyright (C) 1998, 1999, 2000, 2002, 2006 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
++
++   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.  */
++
++#define _LARGEFILE_SOURCE 1
++#include <aio.h>
++#include <errno.h>
++#include <error.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/stat.h>
++#include "tst-aiod.h"
++
++
++/* Prototype for our test function.  */
++extern void do_prepare (int argc, char *argv[]);
++extern int do_test (int argc, char *argv[]);
++
++/* We have a preparation function.  */
++#define PREPARE do_prepare
++
++/* We might need a bit longer timeout.  */
++#define TIMEOUT 20 /* sec */
++
++/* This defines the `main' function and some more.  */
++#include <test-skeleton.c>
++
++
++/* These are for the temporary file we generate.  */
++char *name;
++int fd;
++char *tmpbuf;
++int blksz = 100;
++
++void
++do_prepare (int argc, char *argv[])
++{
++  char name_len;
++
++  name_len = strlen (test_dir);
++  name = malloc (name_len + sizeof ("/aioXXXXXX"));
++  mempcpy (mempcpy (name, test_dir, name_len),
++         "/aioXXXXXX", sizeof ("/aioXXXXXX"));
++  add_temp_file (name);
++
++  /* Open our test file.   */
++  fd = mkstemp (name);
++  if (fd == -1)
++    error (EXIT_FAILURE, errno, "cannot open test file `%s'", name);
++
++  int sz = set_o_direct (fd);
++  if (sz != -1)
++    {
++      blksz = sz;
++      printf ("Using O_DIRECT with block size %d\n", blksz);
++    }
++}
++
++
++static int
++test_file (const void *buf, size_t size, int fd, const char *msg)
++{
++  struct stat st;
++  char *tmp = tmpbuf;
++
++  errno = 0;
++  if (fstat (fd, &st) < 0)
++    {
++      error (0, errno, "%s: failed stat", msg);
++      return 1;
++    }
++
++  if (st.st_size != (off_t) size)
++    {
++      error (0, errno, "%s: wrong size: %lu, should be %lu",
++           msg, (unsigned long int) st.st_size, (unsigned long int) size);
++      return 1;
++    }
++
++  if (pread (fd, tmp, size, 0) != (ssize_t) size)
++    {
++      error (0, errno, "%s: failed pread", msg);
++      return 1;
++    }
++
++  if (memcmp (buf, tmp, size) != 0)
++    {
++      error (0, errno, "%s: failed comparison", msg);
++      return 1;
++    }
++
++  printf ("%s test ok\n", msg);
++
++  return 0;
++}
++
++
++static int
++do_wait (struct aiocb64 **cbp, size_t nent, int allowed_err)
++{
++  int go_on;
++  size_t cnt;
++  int result = 0;
++
++  do
++    {
++      aio_suspend64 ((const struct aiocb64 *const *) cbp, nent, NULL);
++      go_on = 0;
++      for (cnt = 0; cnt < nent; ++cnt)
++      if (cbp[cnt] != NULL)
++        {
++          if (aio_error64 (cbp[cnt]) == EINPROGRESS)
++            go_on = 1;
++          else
++            {
++              if (aio_return64 (cbp[cnt]) == -1
++                  && (allowed_err == 0
++                      || aio_error64 (cbp[cnt]) != allowed_err))
++                {
++                  error (0, aio_error64 (cbp[cnt]), "Operation failed\n");
++                  result = 1;
++                }
++              cbp[cnt] = NULL;
++            }
++        }
++    }
++  while (go_on);
++
++  return result;
++}
++
++
++int
++do_test (int argc, char *argv[])
++{
++  struct aiocb64 cbs[10];
++  struct aiocb64 cbs_fsync;
++  struct aiocb64 *cbp[10];
++  struct aiocb64 *cbp_fsync[1];
++  char *buf;
++  size_t cnt;
++  int result = 0;
++
++  buf = mmap (NULL, 20 * blksz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
++  tmpbuf = buf + 10 * blksz;
++  if (buf == MAP_FAILED)
++    {
++      error (0, errno, "mmap failed");
++      return 1;
++    }
++
++  /* Preparation.  */
++  for (cnt = 0; cnt < 10; ++cnt)
++    {
++      cbs[cnt].aio_fildes = fd;
++      cbs[cnt].aio_reqprio = 0;
++      cbs[cnt].aio_buf = memset (&buf[cnt * blksz], '0' + cnt, blksz);
++      cbs[cnt].aio_nbytes = blksz;
++      cbs[cnt].aio_offset = cnt * blksz;
++      cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE;
++
++      cbp[cnt] = &cbs[cnt];
++    }
++
++  /* First a simple test.  */
++  for (cnt = 10; cnt > 0; )
++    if (aio_write64 (cbp[--cnt]) < 0 && errno == ENOSYS)
++      {
++      error (0, 0, "no aio support in this configuration");
++      return 0;
++      }
++  /* Wait 'til the results are there.  */
++  result |= do_wait (cbp, 10, 0);
++  /* Test this.  */
++  result |= test_file (buf, 10 * blksz, fd, "aio_write");
++
++  /* Read now as we've written it.  */
++  memset (buf, '\0', 10 * blksz);
++  /* Issue the commands.  */
++  for (cnt = 10; cnt > 0; )
++    {
++      --cnt;
++      cbp[cnt] = &cbs[cnt];
++      aio_read64 (cbp[cnt]);
++    }
++  /* Wait 'til the results are there.  */
++  result |= do_wait (cbp, 10, 0);
++  /* Test this.  */
++  for (cnt = 0; cnt < 10 * blksz; ++cnt)
++    if (buf[cnt] != '0' + (cnt / blksz))
++      {
++      result = 1;
++      error (0, 0, "comparison failed for aio_read test");
++      break;
++      }
++
++  if (cnt == 10 * blksz)
++    puts ("aio_read test ok");
++
++  /* Remove the test file contents.  */
++  if (ftruncate64 (fd, 0) < 0)
++    {
++      error (0, errno, "ftruncate failed\n");
++      result = 1;
++    }
++
++  /* Test lio_listio.  */
++  for (cnt = 0; cnt < 10; ++cnt)
++    {
++      cbs[cnt].aio_lio_opcode = LIO_WRITE;
++      cbp[cnt] = &cbs[cnt];
++    }
++  /* Issue the command.  */
++  lio_listio64 (LIO_WAIT, cbp, 10, NULL);
++  /* ...and immediately test it since we started it in wait mode.  */
++  result |= test_file (buf, 10 * blksz, fd, "lio_listio (write)");
++
++  /* Test aio_fsync.  */
++  cbs_fsync.aio_fildes = fd;
++  cbs_fsync.aio_sigevent.sigev_notify = SIGEV_NONE;
++  cbp_fsync[0] = &cbs_fsync;
++
++  /* Remove the test file contents first.  */
++  if (ftruncate64 (fd, 0) < 0)
++    {
++      error (0, errno, "ftruncate failed\n");
++      result = 1;
++    }
++
++  /* Write again.  */
++  for (cnt = 10; cnt > 0; )
++    aio_write64 (cbp[--cnt]);
++
++  if (aio_fsync64 (O_SYNC, &cbs_fsync) < 0)
++    {
++      error (0, errno, "aio_fsync failed\n");
++      result = 1;
++    }
++  result |= do_wait (cbp_fsync, 1, 0);
++
++  /* ...and test since all data should be on disk now.  */
++  result |= test_file (buf, 10 * blksz, fd, "aio_fsync (aio_write)");
++
++  /* Test aio_cancel.  */
++  /* Remove the test file contents first.  */
++  if (ftruncate64 (fd, 0) < 0)
++    {
++      error (0, errno, "ftruncate failed\n");
++      result = 1;
++    }
++
++  /* Write again.  */
++  for (cnt = 10; cnt > 0; )
++    aio_write64 (cbp[--cnt]);
++
++  /* Cancel all requests.  */
++  if (aio_cancel64 (fd, NULL) == -1)
++    printf ("aio_cancel64 (fd, NULL) cannot cancel anything\n");
++
++  result |= do_wait (cbp, 10, ECANCELED);
++
++  /* Another test for aio_cancel.  */
++  /* Remove the test file contents first.  */
++  if (ftruncate64 (fd, 0) < 0)
++    {
++      error (0, errno, "ftruncate failed\n");
++      result = 1;
++    }
++
++  /* Write again.  */
++  for (cnt = 10; cnt > 0; )
++    {
++      --cnt;
++      cbp[cnt] = &cbs[cnt];
++      aio_write64 (cbp[cnt]);
++    }
++  puts ("finished3");
++
++  /* Cancel all requests.  */
++  for (cnt = 10; cnt > 0; )
++    if (aio_cancel64 (fd, cbp[--cnt]) == -1)
++      /* This is not an error.  The request can simply be finished.  */
++      printf ("aio_cancel64 (fd, cbp[%Zd]) cannot be canceled\n", cnt);
++  puts ("finished2");
++
++  result |= do_wait (cbp, 10, ECANCELED);
++
++  puts ("finished");
++
++  return result;
++}
diff --git a/src/patches/glibc/glibc-s390-setjmp.patch b/src/patches/glibc/glibc-s390-setjmp.patch
new file mode 100644 (file)
index 0000000..0358ea5
--- /dev/null
@@ -0,0 +1,16 @@
+2006-01-02  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/s390/bits/setjmp.h (__jmp_buf): Add __s390_jmp_buf
+       struct tag to make C++ happy.
+
+--- libc/sysdeps/s390/bits/setjmp.h    28 Dec 2005 05:41:35 -0000      1.7
++++ libc/sysdeps/s390/bits/setjmp.h    2 Jan 2006 20:46:18 -0000       1.8
+@@ -40,7 +40,7 @@
+ #ifndef       _ASM
+-typedef struct {
++typedef struct __s390_jmp_buf {
+     /* We save registers 6-15.  */
+     long int __gregs[10];
diff --git a/src/patches/glibc/glibc-scalb-namespace.patch b/src/patches/glibc/glibc-scalb-namespace.patch
new file mode 100644 (file)
index 0000000..de6c07b
--- /dev/null
@@ -0,0 +1,25 @@
+2006-02-01  Jakub Jelinek  <jakub@redhat.com>
+
+       * math/bits/mathcalls.h: Guard __END_NAMESPACE_C99 with the
+       same #if condition as corresponding __BEGIN_NAMESPACE_C99.
+       (scalb): Don't define only if __USE_ISOC99.
+
+--- libc/math/bits/mathcalls.h 14 Jan 2006 12:09:23 -0000      1.21
++++ libc/math/bits/mathcalls.h 1 Feb 2006 19:45:21 -0000       1.22
+@@ -353,10 +353,13 @@ __MATHDECL_1 (int, __signbit,, (_Mdouble
+ /* Multiply-add function computed as a ternary operation.  */
+ __MATHCALL (fma,, (_Mdouble_ __x, _Mdouble_ __y, _Mdouble_ __z));
++#endif /* Use ISO C99.  */
++
++#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
+ __END_NAMESPACE_C99
++#endif
+-# if defined __USE_MISC || defined __USE_XOPEN_EXTENDED
++#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED
+ /* Return X times (2 to the Nth power).  */
+ __MATHCALL (scalb,, (_Mdouble_ __x, _Mdouble_ __n));
+-# endif
+-#endif /* Use ISO C99.  */
++#endif
diff --git a/src/patches/glibc/glibc-sched_getaffinity.patch b/src/patches/glibc/glibc-sched_getaffinity.patch
new file mode 100644 (file)
index 0000000..3e83f08
--- /dev/null
@@ -0,0 +1,27 @@
+2006-05-12  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/sched_getaffinity.c: Include sys/param.h.
+       (__sched_getaffinity_new): Don't crash if cpusetsize is smaller than
+       sizeof (cpu_set_t).
+
+--- libc/sysdeps/unix/sysv/linux/sched_getaffinity.c.jj        2005-12-19 08:43:50.000000000 +0100
++++ libc/sysdeps/unix/sysv/linux/sched_getaffinity.c   2006-05-12 17:34:33.000000000 +0200
+@@ -20,6 +20,7 @@
+ #include <sched.h>
+ #include <string.h>
+ #include <sysdep.h>
++#include <sys/param.h>
+ #include <sys/types.h>
+ #include <shlib-compat.h>
+@@ -28,8 +29,8 @@
+ int
+ __sched_getaffinity_new (pid_t pid, size_t cpusetsize, cpu_set_t *cpuset)
+ {
+-  int res = INLINE_SYSCALL (sched_getaffinity, 3, pid, sizeof (cpu_set_t),
+-                          cpuset);
++  int res = INLINE_SYSCALL (sched_getaffinity, 3, pid,
++                          MIN (INT_MAX, cpusetsize), cpuset);
+   if (res != -1)
+     {
+       /* Clean the rest of the memory the kernel didn't do.  */
diff --git a/src/patches/glibc/glibc-sem_timedwait.patch b/src/patches/glibc/glibc-sem_timedwait.patch
new file mode 100644 (file)
index 0000000..3457793
--- /dev/null
@@ -0,0 +1,164 @@
+2007-05-25  Ulrich Drepper  <drepper@redhat.com>
+
+       * Makefile (tests): Add tst-sem10.
+       * tst-sem10.c: New file.
+
+2007-05-25  Ulrich Drepper  <drepper@redhat.com>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait):
+       Move __pthread_enable_asynccancel right before futex syscall.
+       * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S (sem_timedwait):
+       Likewise.
+
+--- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S        9 Apr 2006 02:42:29 -0000       1.8
++++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S        25 May 2007 19:27:03 -0000      1.9
+@@ -79,10 +79,7 @@ sem_timedwait:
+       jae     6f
+       cfi_offset(3, -16)              /* %ebx */
+-7:    call    __pthread_enable_asynccancel
+-      movl    %eax, 8(%esp)
+-
+-      xorl    %ecx, %ecx
++7:    xorl    %ecx, %ecx
+       movl    %esp, %ebx
+       movl    %ecx, %edx
+       movl    $SYS_gettimeofday, %eax
+@@ -105,6 +102,10 @@ sem_timedwait:
+       movl    %ecx, (%esp)    /* Store relative timeout.  */
+       movl    %edx, 4(%esp)
++
++      call    __pthread_enable_asynccancel
++      movl    %eax, 8(%esp)
++
+       movl    28(%esp), %ebx
+       xorl    %ecx, %ecx
+       movl    %esp, %esi
+--- libc/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S   15 May 2007 06:24:23 -0000      1.11
++++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S   25 May 2007 19:27:03 -0000      1.12
+@@ -79,10 +79,7 @@ sem_timedwait:
+       cfi_offset(14, -24)             /* %r14 */
+       jae     6f
+-7:    call    __pthread_enable_asynccancel
+-      movl    %eax, 16(%rsp)
+-
+-      xorq    %rsi, %rsi
++7:    xorq    %rsi, %rsi
+       movq    %rsp, %rdi
+       movq    $VSYSCALL_ADDR_vgettimeofday, %rax
+       callq   *%rax
+@@ -105,6 +102,9 @@ sem_timedwait:
+       movq    %rdi, (%rsp)    /* Store relative timeout.  */
+       movq    %rsi, 8(%rsp)
++      call    __pthread_enable_asynccancel
++      movl    %eax, 16(%rsp)
++
+       movq    %rsp, %r10
+       movq    %r12, %rdi
+       xorq    %rsi, %rsi
+--- libc/nptl/Makefile 18 May 2007 00:52:02 -0000      1.189
++++ libc/nptl/Makefile 26 May 2007 01:30:09 -0000      1.190
+@@ -218,7 +218,7 @@ tests = tst-typesizes \
+       tst-once1 tst-once2 tst-once3 tst-once4 \
+       tst-key1 tst-key2 tst-key3 tst-key4 \
+       tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
+-      tst-sem8 tst-sem9 \
++      tst-sem8 tst-sem9 tst-sem10 \
+       tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
+       tst-align tst-align2 tst-align3 \
+       tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \
+--- libc/nptl/tst-sem10.c      1 Jan 1970 00:00:00 -0000
++++ libc/nptl/tst-sem10.c      26 May 2007 01:23:04 -0000      1.1
+@@ -0,0 +1,88 @@
++/* Copyright (C) 2007 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Jakub Jelinek <jakub@redhat.com>, 2007.
++
++   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 <errno.h>
++#include <pthread.h>
++#include <semaphore.h>
++#include <stdio.h>
++#include <time.h>
++#include <unistd.h>
++#include <sys/time.h>
++
++
++static int
++do_test (void)
++{
++  sem_t s;
++  if (sem_init (&s, 0, 0) == -1)
++    {
++      puts ("sem_init failed");
++      return 1;
++    }
++
++  struct timeval tv;
++  if (gettimeofday (&tv, NULL) != 0)
++    {
++      puts ("gettimeofday failed");
++      return 1;
++    }
++
++  struct timespec ts;
++  TIMEVAL_TO_TIMESPEC (&tv, &ts);
++
++  /* Set ts to yesterday.  */
++  ts.tv_sec -= 86400;
++
++  int type_before;
++  if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &type_before) != 0)
++    {
++      puts ("first pthread_setcanceltype failed");
++      return 1;
++    }
++
++  errno = 0;
++  if (TEMP_FAILURE_RETRY (sem_timedwait (&s, &ts)) != -1)
++    {
++      puts ("sem_timedwait succeeded");
++      return 1;
++    }
++  if (errno != ETIMEDOUT)
++    {
++      printf ("sem_timedwait return errno = %d instead of ETIMEDOUT\n",
++            errno);
++      return 1;
++    }
++
++  int type_after;
++  if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &type_after) != 0)
++    {
++      puts ("second pthread_setcanceltype failed");
++      return 1;
++    }
++  if (type_after != PTHREAD_CANCEL_DEFERRED)
++    {
++      puts ("sem_timedwait changed cancellation type");
++      return 1;
++    }
++
++  return 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-sigwait-EINTR.patch b/src/patches/glibc/glibc-sigwait-EINTR.patch
new file mode 100644 (file)
index 0000000..23f6587
--- /dev/null
@@ -0,0 +1,34 @@
+2005-08-01  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/unix/sysv/linux/sigwait.c (do_sigwait): Restart system
+       call if it returned EINTR.
+
+--- libc/sysdeps/unix/sysv/linux/sigwait.c     28 Sep 2004 22:43:12 -0000      1.11
++++ libc/sysdeps/unix/sysv/linux/sigwait.c     1 Aug 2005 19:25:41 -0000       1.12
+@@ -58,8 +58,11 @@ do_sigwait (const sigset_t *set, int *si
+      real size of the user-level sigset_t.  */
+ #ifdef INTERNAL_SYSCALL
+   INTERNAL_SYSCALL_DECL (err);
+-  ret = INTERNAL_SYSCALL (rt_sigtimedwait, err, 4, CHECK_SIGSET (set),
+-                        NULL, NULL, _NSIG / 8);
++  do
++    ret = INTERNAL_SYSCALL (rt_sigtimedwait, err, 4, CHECK_SIGSET (set),
++                          NULL, NULL, _NSIG / 8);
++  while (INTERNAL_SYSCALL_ERROR_P (ret, err)
++       && INTERNAL_SYSCALL_ERRNO (ret, err) == EINTR);
+   if (! INTERNAL_SYSCALL_ERROR_P (ret, err))
+     {
+       *sig = ret;
+@@ -68,8 +71,10 @@ do_sigwait (const sigset_t *set, int *si
+   else
+     ret = INTERNAL_SYSCALL_ERRNO (ret, err);
+ #else
+-  ret = INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set),
+-                      NULL, NULL, _NSIG / 8);
++  do
++    ret = INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set),
++                        NULL, NULL, _NSIG / 8);
++  while (ret == -1 && errno == EINTR);
+   if (ret != -1)
+     {
+       *sig = ret;
diff --git a/src/patches/glibc/glibc-sockatmark.patch b/src/patches/glibc/glibc-sockatmark.patch
new file mode 100644 (file)
index 0000000..177a4d9
--- /dev/null
@@ -0,0 +1,16 @@
+2005-09-17  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1010]
+       * sysdeps/unix/sockatmark.c (sockatmark): Use SIOCATMARK correctly.
+
+--- libc/sysdeps/unix/sockatmark.c     17 Aug 2001 06:44:34 -0000      1.3
++++ libc/sysdeps/unix/sockatmark.c     17 Sep 2005 23:36:09 -0000      1.4
+@@ -24,5 +24,7 @@ int
+ sockatmark (fd)
+      int fd;
+ {
+-  return __ioctl (fd, SIOCATMARK);
++  int answ;
++
++  return __ioctl (fd, SIOCATMARK, &answ) == -1 ? -1 : answ;
+ }
diff --git a/src/patches/glibc/glibc-stdio-put-error.patch b/src/patches/glibc/glibc-stdio-put-error.patch
new file mode 100644 (file)
index 0000000..ff0a150
--- /dev/null
@@ -0,0 +1,85 @@
+2005-10-17  Ulrich Drepper  <drepper@redhat.com>
+
+       * libio/oldfileops.c (_IO_old_file_xsputn): Fix last patch.
+       Return EOF not 0.
+
+2005-09-04  Ulrich Drepper  <drepper@redhat.com>
+
+       * stdio-common/Makefile (tests): Add tst-put-error.
+       * stdio-common/tst-put-error.c: New file.
+       * libio/fileops.c (_IO_new_file_xsputn): If overflow fails and no more
+       data would have to be written signal error.
+       * libio/oldfileops.c (_IO_old_file_xsputn): Likewise.
+
+--- libc/libio/fileops.c       6 Dec 2004 22:36:56 -0000       1.107
++++ libc/libio/fileops.c       4 Sep 2005 20:07:40 -0000       1.108
+@@ -1338,7 +1338,9 @@ _IO_new_file_xsputn (f, data, n)
+       _IO_size_t block_size, do_write;
+       /* Next flush the (full) buffer. */
+       if (_IO_OVERFLOW (f, EOF) == EOF)
+-      return n - to_do;
++      /* If nothing else has to be written we must not signal the
++         caller that everything has been written.  */
++      return to_do == 0 ? EOF : n - to_do;
+       /* Try to maintain alignment: write a whole number of blocks.
+        dont_write is what gets left over. */
+--- libc/libio/oldfileops.c    14 Sep 2004 04:24:45 -0000      1.28
++++ libc/libio/oldfileops.c    4 Sep 2005 20:09:33 -0000       1.29
+@@ -752,7 +752,7 @@ _IO_old_file_xsputn (f, data, n)
+       _IO_size_t block_size, do_write;
+       /* Next flush the (full) buffer. */
+       if (__overflow (f, EOF) == EOF)
+-      return n - to_do;
++      return to_do == 0 ? EOF : n - to_do;
+       /* Try to maintain alignment: write a whole number of blocks.
+        dont_write is what gets left over. */
+--- libc/stdio-common/Makefile 19 Jul 2005 23:39:22 -0000      1.92
++++ libc/stdio-common/Makefile 4 Sep 2005 20:04:54 -0000       1.93
+@@ -53,7 +53,8 @@ tests := tstscanf test_rdwr test-popen t
+        scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf \
+        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-fgets tst-fwrite
++       tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \
++       tst-fwrite
+ test-srcs = tst-unbputc tst-printf
+--- libc/stdio-common/tst-put-error.c 1 Jan 1970 00:00:00 -0000
++++ libc/stdio-common/tst-put-error.c  5 Sep 2005 20:04:34 -0000       1.2
+@@ -0,0 +1,33 @@
++#include <errno.h>
++#include <error.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++
++
++static int
++do_test (void)
++{
++  char tmpl[] = "/tmp/tst-put-error.XXXXXX";
++  int fd = mkstemp (tmpl);
++  if (fd == -1)
++    error (EXIT_FAILURE, errno, "cannot create temporary file");
++  FILE *fp = fdopen (fd, "w");
++  if (fp == NULL)
++    error (EXIT_FAILURE, errno, "fdopen");
++  setlinebuf (fp);
++  close (fd);
++  unlink (tmpl);
++  int n = fprintf (fp, "hello world\n");
++  printf ("fprintf = %d\n", n);
++  if (n >= 0)
++    error (EXIT_FAILURE, 0, "first fprintf succeeded");
++  n = fprintf (fp, "hello world\n");
++  printf ("fprintf = %d\n", n);
++  if (n >= 0)
++    error (EXIT_FAILURE, 0, "second fprintf succeeded");
++  return 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-strtod--0.patch b/src/patches/glibc/glibc-strtod--0.patch
new file mode 100644 (file)
index 0000000..c05a9e5
--- /dev/null
@@ -0,0 +1,148 @@
+2007-08-03  Jakub Jelinek  <jakub@redhat.com>
+
+       * stdlib/strtod_l.c (____STRTOF_INTERNAL): Properly handle -0.
+       * stdlib/Makefile (tests): Add tst-strtod5.
+       (tst-strtod5-ENV): New.
+       * stdlib/tst-strtod5.c: New file.
+
+--- libc/stdlib/Makefile       11 Jan 2007 17:37:12 -0000      1.117
++++ libc/stdlib/Makefile       3 Aug 2007 16:45:35 -0000       1.118
+@@ -64,7 +64,8 @@ tests                := tst-strtol tst-strtod testmb t
+                  tst-xpg-basename tst-random tst-random2 tst-bsearch      \
+                  tst-limits tst-rand48 bug-strtod tst-setcontext          \
+                  test-a64l tst-qsort tst-system testmb2 bug-strtod2       \
+-                 tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-strtod4
++                 tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-strtod4  \
++                 tst-strtod5
+ include ../Makeconfig
+@@ -116,6 +117,7 @@ test-canon-ARGS = --test-dir=${common-ob
+ tst-strtod-ENV = LOCPATH=$(common-objpfx)localedata
+ tst-strtod3-ENV = LOCPATH=$(common-objpfx)localedata
+ tst-strtod4-ENV = LOCPATH=$(common-objpfx)localedata
++tst-strtod5-ENV = LOCPATH=$(common-objpfx)localedata
+ testmb2-ENV = LOCPATH=$(common-objpfx)localedata
+ # Run a test on the header files we use.
+--- libc/stdlib/strtod_l.c     22 Feb 2007 04:14:02 -0000      1.24
++++ libc/stdlib/strtod_l.c     3 Aug 2007 16:45:24 -0000       1.25
+@@ -700,7 +700,8 @@ ____STRTOF_INTERNAL (nptr, endptr, group
+ #endif
+       /* If TP is at the start of the digits, there was no correctly
+        grouped prefix of the string; so no number found.  */
+-      RETURN (0.0, tp == start_of_digits ? (base == 16 ? cp - 1 : nptr) : tp);
++      RETURN (negative ? -0.0 : 0.0,
++            tp == start_of_digits ? (base == 16 ? cp - 1 : nptr) : tp);
+     }
+   /* Remember first significant digit and read following characters until the
+@@ -759,7 +760,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group
+         if (tp < startp)
+           /* The number is validly grouped, but consists
+              only of zeroes.  The whole value is zero.  */
+-          RETURN (0.0, tp);
++          RETURN (negative ? -0.0 : 0.0, tp);
+         /* Recompute DIG_NO so we won't read more digits than
+            are properly grouped.  */
+@@ -862,7 +863,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group
+                   {
+                     /* Overflow or underflow.  */
+                     __set_errno (ERANGE);
+-                    result = (exp_negative ? 0.0 :
++                    result = (exp_negative ? (negative ? -0.0 : 0.0) :
+                               negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL);
+                   }
+--- libc/stdlib/tst-strtod5.c  1 Jan 1970 00:00:00 -0000
++++ libc/stdlib/tst-strtod5.c  3 Aug 2007 16:45:08 -0000       1.1
+@@ -0,0 +1,88 @@
++#include <locale.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <math.h>
++
++#define NBSP "\xc2\xa0"
++
++static const struct
++{
++  const char *in;
++  int group;
++  double expected;
++} tests[] =
++  {
++    { "0", 0, 0.0 },
++    { "000", 0, 0.0 },
++    { "-0", 0, -0.0 },
++    { "-000", 0, -0.0 },
++    { "0,", 0, 0.0 },
++    { "-0,", 0, -0.0 },
++    { "0,0", 0, 0.0 },
++    { "-0,0", 0, -0.0 },
++    { "0e-10", 0, 0.0 },
++    { "-0e-10", 0, -0.0 },
++    { "0,e-10", 0, 0.0 },
++    { "-0,e-10", 0, -0.0 },
++    { "0,0e-10", 0, 0.0 },
++    { "-0,0e-10", 0, -0.0 },
++    { "0e-1000000", 0, 0.0 },
++    { "-0e-1000000", 0, -0.0 },
++    { "0,0e-1000000", 0, 0.0 },
++    { "-0,0e-1000000", 0, -0.0 },
++    { "0", 1, 0.0 },
++    { "000", 1, 0.0 },
++    { "-0", 1, -0.0 },
++    { "-000", 1, -0.0 },
++    { "0e-10", 1, 0.0 },
++    { "-0e-10", 1, -0.0 },
++    { "0e-1000000", 1, 0.0 },
++    { "-0e-1000000", 1, -0.0 },
++    { "000"NBSP"000"NBSP"000", 1, 0.0 },
++    { "-000"NBSP"000"NBSP"000", 1, -0.0 }
++  };
++#define NTESTS (sizeof (tests) / sizeof (tests[0]))
++
++
++static int
++do_test (void)
++{
++  if (setlocale (LC_ALL, "cs_CZ.UTF-8") == NULL)
++    {
++      puts ("could not set locale");
++      return 1;
++    }
++
++  int status = 0;
++
++  for (int i = 0; i < NTESTS; ++i)
++    {
++      char *ep;
++      double r;
++
++      if (tests[i].group)
++      r = __strtod_internal (tests[i].in, &ep, 1);
++      else
++      r = strtod (tests[i].in, &ep);
++
++      if (*ep != '\0')
++      {
++        printf ("%d: got rest string \"%s\", expected \"\"\n", i, ep);
++        status = 1;
++      }
++
++      if (r != tests[i].expected
++        || copysign (10.0, r) != copysign (10.0, tests[i].expected))
++      {
++        printf ("%d: got wrong results %g, expected %g\n",
++                i, r, tests[i].expected);
++        status = 1;
++      }
++    }
++
++  return status;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-strtod.patch b/src/patches/glibc/glibc-strtod.patch
new file mode 100644 (file)
index 0000000..a6f37aa
--- /dev/null
@@ -0,0 +1,301 @@
+2006-12-11  Ulrich Drepper  <drepper@redhat.com>
+
+       * stdlib/strtod_l.c (____STRTOF_INTERNAL): Parse thousand
+       separators also if no non-zero digits found.
+       * stdlib/Makefile (tests): Add tst-strtod3.
+
+2006-12-09  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #3664]
+       * stdlib/strtod_l.c (____STRTOF_INTERNAL): Fix test to recognize
+       empty parsed strings.
+       * stdlib/Makefile (tests): Add tst-strtod2.
+       * stdlib/tst-strtod2.c: New file.
+
+       [BZ #3673]
+       * stdlib/strtod_l.c (____STRTOF_INTERNAL): Fix exp_limit
+       computation.
+       * stdlib/Makefile (tests): Add tst-atof2.
+       * stdlib/tst-atof2.c: New file.
+
+       [BZ #3674]
+       * stdlib/strtod_l.c (____STRTOF_INTERNAL): Adjust exponent value
+       correctly if removing trailing zero of hex-float.
+       * stdlib/Makefile (tests): Add tst-atof1.
+       * stdlib/tst-atof1.c: New file.
+
+--- libc/stdlib/strtod_l.c     14 Jan 2006 12:09:09 -0000      1.14
++++ libc/stdlib/strtod_l.c     11 Dec 2006 21:43:48 -0000      1.19
+@@ -662,20 +662,20 @@ ____STRTOF_INTERNAL (nptr, endptr, group
+   /* If no other digit but a '0' is found the result is 0.0.
+      Return current read pointer.  */
+-  if ((c < L_('0') || c > L_('9'))
+-      && (base == 16 && (c < (CHAR_TYPE) TOLOWER (L_('a'))
+-                       || c > (CHAR_TYPE) TOLOWER (L_('f'))))
++  if (!((c >= L_('0') && c <= L_('9'))
++      || (base == 16 && ((CHAR_TYPE) TOLOWER (c) >= L_('a')
++                         && (CHAR_TYPE) TOLOWER (c) <= L_('f')))
+ #ifdef USE_WIDE_CHAR
+-      && c != (wint_t) decimal
++      || c == (wint_t) decimal
+ #else
+-      && ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
++      || ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
+             if (decimal[cnt] != cp[cnt])
+               break;
+-          decimal[cnt] != '\0'; })
++            decimal[cnt] == '\0'; })
+ #endif
+-      && (base == 16 && (cp == start_of_digits
+-                       || (CHAR_TYPE) TOLOWER (c) != L_('p')))
+-      && (base != 16 && (CHAR_TYPE) TOLOWER (c) != L_('e')))
++      || (base == 16 && (cp != start_of_digits
++                         && (CHAR_TYPE) TOLOWER (c) == L_('p')))
++      || (base != 16 && (CHAR_TYPE) TOLOWER (c) == L_('e'))))
+     {
+ #ifdef USE_WIDE_CHAR
+       tp = __correctly_grouped_prefixwc (start_of_digits, cp, thousands,
+@@ -721,7 +721,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group
+       c = *++cp;
+     }
+-  if (grouping && dig_no > 0)
++  if (grouping && cp > start_of_digits)
+     {
+       /* Check the grouping of the digits.  */
+ #ifdef USE_WIDE_CHAR
+@@ -759,13 +759,15 @@ ____STRTOF_INTERNAL (nptr, endptr, group
+       }
+     }
+-  /* We have the number digits in the integer part.  Whether these are all or
+-     any is really a fractional digit will be decided later.  */
++  /* We have the number of digits in the integer part.  Whether these
++     are all or any is really a fractional digit will be decided
++     later.  */
+   int_no = dig_no;
+   lead_zero = int_no == 0 ? -1 : 0;
+-  /* Read the fractional digits.  A special case are the 'american style'
+-     numbers like `16.' i.e. with decimal but without trailing digits.  */
++  /* Read the fractional digits.  A special case are the 'american
++     style' numbers like `16.' i.e. with decimal point but without
++     trailing digits.  */
+   if (
+ #ifdef USE_WIDE_CHAR
+       c == (wint_t) decimal
+@@ -815,15 +817,16 @@ ____STRTOF_INTERNAL (nptr, endptr, group
+         if (base == 16)
+           exp_limit = (exp_negative ?
+                        -MIN_EXP + MANT_DIG + 4 * int_no :
+-                       MAX_EXP - 4 * int_no + lead_zero);
++                       MAX_EXP - 4 * int_no + 4 * lead_zero + 3);
+         else
+           exp_limit = (exp_negative ?
+                        -MIN_10_EXP + MANT_DIG + int_no :
+-                       MAX_10_EXP - int_no + lead_zero);
++                       MAX_10_EXP - int_no + lead_zero + 1);
+         do
+           {
+             exponent *= 10;
++            exponent += c - L_('0');
+             if (exponent > exp_limit)
+               /* The exponent is too large/small to represent a valid
+@@ -853,7 +856,6 @@ ____STRTOF_INTERNAL (nptr, endptr, group
+                 /* NOTREACHED */
+               }
+-            exponent += c - L_('0');
+             c = *++cp;
+           }
+         while (c >= L_('0') && c <= L_('9'));
+@@ -888,7 +890,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group
+       --expp;
+       --dig_no;
+       --int_no;
+-      ++exponent;
++      exponent += base == 16 ? 4 : 1;
+       }
+     while (dig_no > 0 && exponent < 0);
+--- libc/stdlib/Makefile       28 Oct 2006 06:44:04 -0000      1.110
++++ libc/stdlib/Makefile       11 Dec 2006 21:43:10 -0000      1.113
+@@ -66,7 +66,8 @@ tests                := tst-strtol tst-strtod testmb t
+                  test-canon test-canon2 tst-strtoll tst-environ           \
+                  tst-xpg-basename tst-random tst-random2 tst-bsearch      \
+                  tst-limits tst-rand48 bug-strtod tst-setcontext          \
+-                 test-a64l tst-qsort tst-system testmb2 bug-strtod2
++                 test-a64l tst-qsort tst-system testmb2 bug-strtod2       \
++                 tst-atof1 tst-atof2 tst-strtod2 tst-strtod3
+ include ../Makeconfig
+--- libc/stdlib/tst-atof1.c    1 Jan 1970 00:00:00 -0000
++++ libc/stdlib/tst-atof1.c    10 Dec 2006 09:54:35 -0000      1.1
+@@ -0,0 +1,19 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++static int
++do_test (void)
++{
++  char buf[100];
++  snprintf (buf, sizeof (buf), "%g", atof ("0x10p-1"));
++  if (strcmp (buf, "8") != 0)
++    {
++      printf ("got \"%s\", expected \"8\"\n", buf);
++      return 1;
++    }
++  return 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/stdlib/tst-atof2.c    1 Jan 1970 00:00:00 -0000
++++ libc/stdlib/tst-atof2.c    10 Dec 2006 01:10:17 -0000      1.1
+@@ -0,0 +1,55 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++
++static const struct
++{
++  const char *str;
++  const char *expected;
++} tests[] =
++  {
++    { "1e308", "1e+308" },
++    { "100000000e300", "1e+308" },
++    { "0x1p1023", "8.98847e+307" },
++    { "0x1000p1011", "8.98847e+307" },
++    { "0x1p1020", "1.12356e+307" },
++    { "0x0.00001p1040", "1.12356e+307" },
++    { "1e-307", "1e-307" },
++    { "0.000001e-301", "1e-307" },
++    { "0.0000001e-300", "1e-307" },
++    { "0.00000001e-299", "1e-307" },
++    { "1000000e-313", "1e-307" },
++    { "10000000e-314", "1e-307" },
++    { "100000000e-315", "1e-307" },
++    { "0x1p-1021", "4.45015e-308" },
++    { "0x1000p-1033", "4.45015e-308" },
++    { "0x10000p-1037", "4.45015e-308" },
++    { "0x0.001p-1009", "4.45015e-308" },
++    { "0x0.0001p-1005", "4.45015e-308" },
++  };
++#define NTESTS (sizeof (tests) / sizeof (tests[0]))
++
++
++static int
++do_test (void)
++{
++  int status = 0;
++
++  for (int i = 0; i < NTESTS; ++i)
++    {
++      char buf[100];
++      snprintf (buf, sizeof (buf), "%g", atof (tests[i].str));
++      if (strcmp (buf, tests[i].expected) != 0)
++      {
++        printf ("%d: got \"%s\", expected \"%s\"\n",
++                i, buf, tests[i].expected);
++        status = 1;
++      }
++    }
++
++  return status;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/stdlib/tst-strtod2.c  1 Jan 1970 00:00:00 -0000
++++ libc/stdlib/tst-strtod2.c  11 Dec 2006 21:36:30 -0000      1.2
+@@ -0,0 +1,25 @@
++#include <stdio.h>
++#include <stdlib.h>
++
++static int
++do_test (void)
++{
++  int status = 0;
++  const char s[] = "0x";
++  char *ep;
++  double r = strtod (s, &ep);
++  if (r != 0)
++    {
++      printf ("r = %g, expect 0\n", r);
++      status = 1;
++    }
++  if (ep != s + 1)
++    {
++      printf ("strtod parsed %ju characters, expected 1\n", ep - s);
++      status = 1;
++    }
++  return status;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--- libc/stdlib/tst-strtod3.c  1 Jan 1970 00:00:00 -0000
++++ libc/stdlib/tst-strtod3.c  11 Dec 2006 21:43:01 -0000      1.1
+@@ -0,0 +1,55 @@
++#include <locale.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++static const struct
++{
++  const char *in;
++  const char *out;
++  double expected;
++} tests[] =
++  {
++    { "000,,,e1", ",,,e1", 0.0 },
++    { "000e1", "", 0.0 },
++    { "000,1e1", ",1e1", 0.0 }
++  };
++#define NTESTS (sizeof (tests) / sizeof (tests[0]))
++
++
++static int
++do_test (void)
++{
++  if (setlocale (LC_ALL, "en_US.ISO-8859-1") == NULL)
++    {
++      puts ("could not set locale");
++      return 1;
++    }
++
++  int status = 0;
++
++  for (int i = 0; i < NTESTS; ++i)
++    {
++      char *ep;
++      double r = __strtod_internal (tests[i].in, &ep, 1);
++
++      if (strcmp (ep, tests[i].out) != 0)
++      {
++        printf ("%d: got rest string \"%s\", expected \"%s\"\n",
++                i, ep, tests[i].out);
++        status = 1;
++      }
++
++      if (r != tests[i].expected)
++      {
++        printf ("%d: got wrong results %g, expected %g\n",
++                i, r, tests[i].expected);
++        status = 1;
++      }
++    }
++
++  return status;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-strxfrm.patch b/src/patches/glibc/glibc-strxfrm.patch
new file mode 100644 (file)
index 0000000..f34d0cb
--- /dev/null
@@ -0,0 +1,149 @@
+2006-11-10  Jakub Jelinek  <jakub@redhat.com>
+
+       * string/strxfrm_l.c (STRXFRM): Fix trailing \1 optimization
+       if N is one bigger than return value.
+       * string/tst-strxfrm2.c (do_test): Also test strxfrm with l1 + 1
+       and l1 last arguments, if buf is defined, verify the return value
+       equals to strlen (buf) and verify no byte beyond passed length
+       is modified.
+
+2006-11-09  Ulrich Drepper  <drepper@redhat.com>
+
+       * string/Makefile (tests): Add tst-strxfrm2.
+       * string/tst-strxfrm2.c: New file.
+
+2006-11-08  Jakub Jelinek  <jakub@redhat.com>
+
+       * string/strxfrm_l.c (STRXFRM): Do the trailing \1 removal
+       optimization even if needed > n.
+
+--- libc/string/Makefile       4 Jun 2006 16:35:25 -0000       1.69
++++ libc/string/Makefile       9 Nov 2006 20:19:24 -0000       1.70
+@@ -54,7 +54,7 @@ tests                := tester inl-tester noinl-tester
+                  bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap      \
+                  tst-strtok tst-strxfrm bug-strcoll1 tst-strfry       \
+                  bug-strtok1 $(addprefix test-,$(strop-tests))        \
+-                 bug-envz1
++                 bug-envz1 tst-strxfrm2
+ distribute    := memcopy.h pagecopy.h tst-svc.expect test-string.h
+--- libc/string/strxfrm_l.c    15 Oct 2005 20:49:18 -0000      1.5
++++ libc/string/strxfrm_l.c    10 Nov 2006 15:18:46 -0000      1.7
+@@ -96,6 +97,7 @@ STRXFRM (STRING_TYPE *dest, const STRING
+   const int32_t *indirect;
+   uint_fast32_t pass;
+   size_t needed;
++  size_t last_needed;
+   const USTRING_TYPE *usrc;
+   size_t srclen = STRLEN (src);
+   int32_t *idxarr;
+@@ -197,6 +199,7 @@ STRXFRM (STRING_TYPE *dest, const STRING
+        this is true for all of them.  */
+       int position = rule & sort_position;
++      last_needed = needed;
+       if (position == 0)
+       {
+         for (idxcnt = 0; idxcnt < idxmax; ++idxcnt)
+@@ -426,11 +429,11 @@ STRXFRM (STRING_TYPE *dest, const STRING
+      a `position' rule at the end and if no non-ignored character
+      is found the last \1 byte is immediately followed by a \0 byte
+      signalling this.  We can avoid the \1 byte(s).  */
+-  if (needed <= n && needed > 2 && dest[needed - 2] == L('\1'))
++  if (needed > 2 && needed == last_needed + 1)
+     {
+       /* Remove the \1 byte.  */
+-      --needed;
+-      dest[needed - 1] = L('\0');
++      if (--needed <= n)
++      dest[needed - 1] = L('\0');
+     }
+   /* Free the memory if needed.  */
+--- libc/string/tst-strxfrm2.c 1 Jan 1970 00:00:00 -0000
++++ libc/string/tst-strxfrm2.c 10 Nov 2006 15:20:23 -0000      1.2
+@@ -0,0 +1,83 @@
++#include <locale.h>
++#include <stdio.h>
++#include <string.h>
++
++static int
++do_test (void)
++{
++  int res = 0;
++
++  char buf[20];
++  size_t l1 = strxfrm (NULL, "ab", 0);
++  size_t l2 = strxfrm (buf, "ab", 1);
++  size_t l3 = strxfrm (buf, "ab", sizeof (buf));
++  if (l3 < sizeof (buf) && strlen (buf) != l3)
++    {
++      puts ("C locale l3 test failed");
++      res = 1;
++    }
++
++  size_t l4 = strxfrm (buf, "ab", l1 + 1);
++  if (l4 < l1 + 1 && strlen (buf) != l4)
++    {
++      puts ("C locale l4 test failed");
++      res = 1;
++    }
++
++  buf[l1] = 'Z';
++  size_t l5 = strxfrm (buf, "ab", l1);
++  if (buf[l1] != 'Z')
++    {
++      puts ("C locale l5 test failed");
++      res = 1;
++    }
++
++  if (l1 != l2 || l1 != l3 || l1 != l4 || l1 != l5)
++    {
++      puts ("C locale retval test failed");
++      res = 1;
++    }
++
++  if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL)
++    {
++      puts ("setlocale failed");
++      res = 1;
++    }
++  else
++    {
++      l1 = strxfrm (NULL, "ab", 0);
++      l2 = strxfrm (buf, "ab", 1);
++      l3 = strxfrm (buf, "ab", sizeof (buf));
++      if (l3 < sizeof (buf) && strlen (buf) != l3)
++      {
++        puts ("UTF-8 locale l3 test failed");
++        res = 1;
++      }
++
++      l4 = strxfrm (buf, "ab", l1 + 1);
++      if (l4 < l1 + 1 && strlen (buf) != l4)
++      {
++        puts ("UTF-8 locale l4 test failed");
++        res = 1;
++      }
++
++      buf[l1] = 'Z';
++      l5 = strxfrm (buf, "ab", l1);
++      if (buf[l1] != 'Z')
++      {
++        puts ("UTF-8 locale l5 test failed");
++        res = 1;
++      }
++
++      if (l1 != l2 || l1 != l3 || l1 != l4 || l1 != l5)
++      {
++        puts ("UTF-8 locale retval test failed");
++        res = 1;
++      }
++    }
++
++  return res;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-sysconf-intel-caches.patch b/src/patches/glibc/glibc-sysconf-intel-caches.patch
new file mode 100644 (file)
index 0000000..cfb5196
--- /dev/null
@@ -0,0 +1,76 @@
+2006-02-01  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/unix/sysv/linux/i386/sysconf.c (intel_02_known): Add
+       some more entries.
+       * sysdeps/unix/sysv/linux/x86_64/sysconf.c (intel_02_known): Likewise.
+
+--- libc/sysdeps/unix/sysv/linux/i386/sysconf.c        5 Oct 2004 09:20:50 -0000       1.5
++++ libc/sysdeps/unix/sysv/linux/i386/sysconf.c        1 Feb 2006 18:26:19 -0000       1.6
+@@ -84,11 +84,24 @@ static const struct intel_02_cache_info
+     { 0x29, _SC_LEVEL3_CACHE_SIZE, 4194304, 8, 64 },
+     { 0x2c, _SC_LEVEL1_DCACHE_SIZE, 32768, 8, 64 },
+     { 0x30, _SC_LEVEL1_ICACHE_SIZE, 32768, 8, 64 },
++    { 0x39, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 64 },
++    { 0x3a, _SC_LEVEL2_CACHE_SIZE, 196608, 6, 64 },
++    { 0x3b, _SC_LEVEL2_CACHE_SIZE, 131072, 2, 64 },
++    { 0x3c, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 64 },
++    { 0x3d, _SC_LEVEL2_CACHE_SIZE, 393216, 6, 64 },
++    { 0x3e, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 },
+     { 0x41, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 32 },
+     { 0x42, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 32 },
+     { 0x43, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 32 },
+     { 0x44, _SC_LEVEL2_CACHE_SIZE, 1048576, 4, 32 },
+     { 0x45, _SC_LEVEL2_CACHE_SIZE, 2097152, 4, 32 },
++    { 0x46, _SC_LEVEL3_CACHE_SIZE, 4194304, 4, 64 },
++    { 0x47, _SC_LEVEL3_CACHE_SIZE, 8388608, 8, 64 },
++    { 0x49, _SC_LEVEL3_CACHE_SIZE, 4194304, 16, 64 },
++    { 0x4a, _SC_LEVEL3_CACHE_SIZE, 6291456, 12, 64 },
++    { 0x4b, _SC_LEVEL3_CACHE_SIZE, 8388608, 16, 64 },
++    { 0x4c, _SC_LEVEL3_CACHE_SIZE, 12582912, 12, 64 },
++    { 0x4d, _SC_LEVEL3_CACHE_SIZE, 16777216, 16, 64 },
+     { 0x60, _SC_LEVEL1_DCACHE_SIZE, 16384, 8, 64 },
+     { 0x66, _SC_LEVEL1_DCACHE_SIZE, 8192, 4, 64 },
+     { 0x67, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 64 },
+@@ -99,6 +112,7 @@ static const struct intel_02_cache_info
+     { 0x7b, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 64 },
+     { 0x7c, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 },
+     { 0x7d, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 64 },
++    { 0x7f, _SC_LEVEL2_CACHE_SIZE, 524288, 2, 64 },
+     { 0x82, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 32 },
+     { 0x83, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 32 },
+     { 0x84, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 32 },
+--- libc/sysdeps/unix/sysv/linux/x86_64/sysconf.c      5 Oct 2004 09:23:06 -0000       1.3
++++ libc/sysdeps/unix/sysv/linux/x86_64/sysconf.c      2 Feb 2006 05:33:33 -0000       1.4
+@@ -45,11 +45,24 @@ static const struct intel_02_cache_info
+     { 0x29, _SC_LEVEL3_CACHE_SIZE, 4194304, 8, 64 },
+     { 0x2c, _SC_LEVEL1_DCACHE_SIZE, 32768, 8, 64 },
+     { 0x30, _SC_LEVEL1_ICACHE_SIZE, 32768, 8, 64 },
++    { 0x39, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 64 },
++    { 0x3a, _SC_LEVEL2_CACHE_SIZE, 196608, 6, 64 },
++    { 0x3b, _SC_LEVEL2_CACHE_SIZE, 131072, 2, 64 },
++    { 0x3c, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 64 },
++    { 0x3d, _SC_LEVEL2_CACHE_SIZE, 393216, 6, 64 },
++    { 0x3e, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 },
+     { 0x41, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 32 },
+     { 0x42, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 32 },
+     { 0x43, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 32 },
+     { 0x44, _SC_LEVEL2_CACHE_SIZE, 1048576, 4, 32 },
+     { 0x45, _SC_LEVEL2_CACHE_SIZE, 2097152, 4, 32 },
++    { 0x46, _SC_LEVEL3_CACHE_SIZE, 4194304, 4, 64 },
++    { 0x47, _SC_LEVEL3_CACHE_SIZE, 8388608, 8, 64 },
++    { 0x49, _SC_LEVEL3_CACHE_SIZE, 4194304, 16, 64 },
++    { 0x4a, _SC_LEVEL3_CACHE_SIZE, 6291456, 12, 64 },
++    { 0x4b, _SC_LEVEL3_CACHE_SIZE, 8388608, 16, 64 },
++    { 0x4c, _SC_LEVEL3_CACHE_SIZE, 12582912, 12, 64 },
++    { 0x4d, _SC_LEVEL3_CACHE_SIZE, 16777216, 16, 64 },
+     { 0x60, _SC_LEVEL1_DCACHE_SIZE, 16384, 8, 64 },
+     { 0x66, _SC_LEVEL1_DCACHE_SIZE, 8192, 4, 64 },
+     { 0x67, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 64 },
+@@ -60,6 +73,7 @@ static const struct intel_02_cache_info
+     { 0x7b, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 64 },
+     { 0x7c, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 },
+     { 0x7d, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 64 },
++    { 0x7f, _SC_LEVEL2_CACHE_SIZE, 524288, 2, 64 },
+     { 0x82, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 32 },
+     { 0x83, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 32 },
+     { 0x84, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 32 },
diff --git a/src/patches/glibc/glibc-tgmath-type.patch b/src/patches/glibc/glibc-tgmath-type.patch
new file mode 100644 (file)
index 0000000..63e3a83
--- /dev/null
@@ -0,0 +1,142 @@
+2005-10-14  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #865]
+       * math/tgmath.h: Correctly determine result type for
+       __TGMATH_BINARY_REAL_ONLY,
+       __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY,
+       __TGMATH_TERNARY_REAL_ONLY, and __TGMATH_BINARY_REAL_IMAG.
+
+2005-09-17  Andreas Jaeger  <aj@suse.de>
+
+       [BZ #865]
+       * math/test-tgmath-int.c: New file.
+       * math/Makefile (tests): Add test-tgmath-int.
+
+--- libc/math/tgmath.h 7 May 2004 02:13:19 -0000       1.24
++++ libc/math/tgmath.h 15 Oct 2005 00:13:49 -0000      1.25
+@@ -98,7 +98,8 @@
+                      __tgmres; }))
+ # define __TGMATH_BINARY_REAL_ONLY(Val1, Val2, Fct) \
+-     (__extension__ ({ __tgmath_real_type ((Val1) + (Val2)) __tgmres;       \
++     (__extension__ ({ __typeof((__tgmath_real_type (Val1)) 0               \
++                              + (__tgmath_real_type (Val2)) 0) __tgmres;    \
+                      if ((sizeof (Val1) > sizeof (double)                   \
+                           || sizeof (Val2) > sizeof (double))               \
+                          && __builtin_classify_type ((Val1) + (Val2)) == 8) \
+@@ -113,7 +114,8 @@
+                      __tgmres; }))
+ # define __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY(Val1, Val2, Val3, Fct) \
+-     (__extension__ ({ __tgmath_real_type ((Val1) + (Val2)) __tgmres;       \
++     (__extension__ ({ __typeof((__tgmath_real_type (Val1)) 0               \
++                              + (__tgmath_real_type (Val2)) 0) __tgmres;    \
+                      if ((sizeof (Val1) > sizeof (double)                   \
+                           || sizeof (Val2) > sizeof (double))               \
+                          && __builtin_classify_type ((Val1) + (Val2)) == 8) \
+@@ -128,7 +130,9 @@
+                      __tgmres; }))
+ # define __TGMATH_TERNARY_REAL_ONLY(Val1, Val2, Val3, Fct) \
+-     (__extension__ ({ __tgmath_real_type ((Val1) + (Val2) + (Val3)) __tgmres;\
++     (__extension__ ({ __typeof((__tgmath_real_type (Val1)) 0               \
++                              + (__tgmath_real_type (Val2)) 0               \
++                              + (__tgmath_real_type (Val3)) 0) __tgmres;    \
+                      if ((sizeof (Val1) > sizeof (double)                   \
+                           || sizeof (Val2) > sizeof (double)                \
+                           || sizeof (Val3) > sizeof (double))               \
+@@ -209,7 +213,8 @@
+ /* XXX This definition has to be changed as soon as the compiler understands
+    the imaginary keyword.  */
+ # define __TGMATH_BINARY_REAL_IMAG(Val1, Val2, Fct, Cfct) \
+-     (__extension__ ({ __tgmath_real_type ((Val1) + (Val2)) __tgmres;       \
++     (__extension__ ({ __typeof((__tgmath_real_type (Val1)) 0               \
++                              + (__tgmath_real_type (Val2)) 0) __tgmres;    \
+                      if ((sizeof (__real__ (Val1)) > sizeof (double)        \
+                           || sizeof (__real__ (Val2)) > sizeof (double))    \
+                          && __builtin_classify_type (__real__ (Val1)        \
+--- libc/math/Makefile 6 May 2004 18:58:08 -0000       1.126
++++ libc/math/Makefile 15 Oct 2005 00:15:45 -0000      1.127
+@@ -89,7 +89,7 @@ distribute += $(filter-out $(generated),
+ # Rules for the test suite.
+ tests = test-matherr test-fenv atest-exp atest-sincos atest-exp2 basic-test \
+       test-misc test-fpucw tst-definitions test-tgmath test-tgmath-ret \
+-      bug-nextafter bug-nexttoward bug-tgmath1
++      bug-nextafter bug-nexttoward bug-tgmath1 test-tgmath-int
+ # We do the `long double' tests only if this data type is available and
+ # distinct from `double'.
+ test-longdouble-yes = test-ldouble test-ildoubl
+--- libc/math/test-tgmath-int.c 1 Jan 1970 00:00:00 -0000
++++ libc/math/test-tgmath-int.c        15 Oct 2005 00:15:17 -0000      1.1
+@@ -0,0 +1,71 @@
++/* Test compilation of tgmath macros.
++   Copyright (C) 2005 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Andreas Jaeger <aj@suse.de>, 2005.
++
++   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 <math.h>
++#include <complex.h>
++#include <tgmath.h>
++#include <stdio.h>
++
++static int errors = 0;
++
++static void
++our_error (const char *c)
++{
++  puts (c);
++  ++errors;
++}
++
++#define CHECK_RET_CONST_TYPE(func, rettype, name)                     \
++  if (sizeof (func) != sizeof (rettype))                              \
++    our_error ("Return size of " #name " is " #func" wrong");
++
++#define CHECK_RET_CONST_FLOAT(func, name)             \
++  CHECK_RET_CONST_TYPE (func, float, name)
++
++#define CHECK_RET_CONST_DOUBLE(func, name)            \
++  CHECK_RET_CONST_TYPE (func, double, name)
++
++static int
++do_test (void)
++{
++  int i;
++  float f;
++  double d;
++
++  CHECK_RET_CONST_DOUBLE (sin (i), "sin (i)");
++  CHECK_RET_CONST_DOUBLE (pow (i, i), "pow (i, i)");
++  CHECK_RET_CONST_DOUBLE (pow (i, i), "pow (i, i)");
++  CHECK_RET_CONST_DOUBLE (pow (i, f), "pow (i, f)");
++  CHECK_RET_CONST_DOUBLE (pow (i, d), "pow (i, d)");
++  CHECK_RET_CONST_DOUBLE (pow (f, i), "pow (f, i)");
++  CHECK_RET_CONST_DOUBLE (pow (d, i), "pow (d, i)");
++  CHECK_RET_CONST_DOUBLE (fma (i, i, i), "fma (i, i, i)");
++  CHECK_RET_CONST_DOUBLE (fma (f, i, i), "fma (f, i, i)");
++  CHECK_RET_CONST_DOUBLE (fma (i, f, i), "fma (i, f, i)");
++  CHECK_RET_CONST_DOUBLE (fma (i, i, f), "fma (i, i, f)");
++  CHECK_RET_CONST_DOUBLE (fma (d, i, i), "fma (d, i, i)");
++  CHECK_RET_CONST_DOUBLE (fma (i, d, i), "fma (i, d, i)");
++  CHECK_RET_CONST_DOUBLE (fma (i, i, d), "fma (i, i, d)");
++
++  return errors != 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-tls-model-ie.patch b/src/patches/glibc/glibc-tls-model-ie.patch
new file mode 100644 (file)
index 0000000..00128db
--- /dev/null
@@ -0,0 +1,17 @@
+2005-09-22  Roland McGrath  <roland@redhat.com>
+
+       * elf/dl-tsd.c (__libc_dl_error_tsd): Use attribute_tls_model_ie for
+       static __thread variable.
+       From Alexandre Oliva <aoliva@redhat.com>
+
+--- libc/elf/dl-tsd.c  4 Dec 2002 12:27:51 -0000       1.3
++++ libc/elf/dl-tsd.c  22 Sep 2005 07:29:47 -0000      1.4
+@@ -49,7 +49,7 @@ void **(*_dl_error_catch_tsd) (void) __a
+ void ** __attribute__ ((const))
+ __libc_dl_error_tsd (void)
+ {
+-  static __thread void *data;
++  static __thread void *data attribute_tls_model_ie;
+   return &data;
+ }
diff --git a/src/patches/glibc/glibc-tst-initializers1.patch b/src/patches/glibc/glibc-tst-initializers1.patch
new file mode 100644 (file)
index 0000000..584b3ce
--- /dev/null
@@ -0,0 +1,55 @@
+2006-01-09  Roland McGrath  <roland@redhat.com>
+
+       * tst-initializers1-c89.c: New file.
+       * tst-initializers1-c99.c: New file.
+       * tst-initializers1-gnu89.c: New file.
+       * tst-initializers1-gnu99.c: New file.
+       * Makefile (tests): Add them.
+       (CFLAGS-tst-initializers1-c89.c): New variable.
+       (CFLAGS-tst-initializers1-c99.c): New variable.
+       (CFLAGS-tst-initializers1-gnu89.c): New variable.
+       (CFLAGS-tst-initializers1-gnu99.c): New variable.
+
+--- libc/nptl/Makefile 5 Jan 2006 08:16:20 -0000       1.175
++++ libc/nptl/Makefile 9 Jan 2006 23:04:44 -0000       1.176
+@@ -246,7 +246,8 @@ tests = tst-typesizes \
+       tst-backtrace1 \
+       tst-oddstacklimit \
+       tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x \
+-      tst-getpid1 tst-getpid2 tst-initializers1
++      tst-getpid1 tst-getpid2 \
++      tst-initializers1 $(patsubst %,tst-initializers1-%,c89 gnu89 c99 gnu99)
+ xtests = tst-setuid1 tst-setuid1-static
+ # Files which must not be linked with libpthread.
+@@ -415,7 +416,13 @@ CFLAGS-tst-oncex3.c += -fexceptions
+ CFLAGS-tst-oncex4.c += -fexceptions
+ CFLAGS-tst-align.c += $(stack-align-test-flags)
+ CFLAGS-tst-align3.c += $(stack-align-test-flags)
+-CFLAGS-tst-initializers1.c += -W -Wall -Werror
++CFLAGS-tst-initializers1.c = -W -Wall -Werror
++CFLAGS-tst-initializers1-< = $(CFLAGS-tst-initializers1.c) \
++                           $(patsubst tst-initializers1-%.c,-std=%,$<)
++CFLAGS-tst-initializers1-c89.c = $(CFLAGS-tst-initializers1-<)
++CFLAGS-tst-initializers1-c99.c = $(CFLAGS-tst-initializers1-<)
++CFLAGS-tst-initializers1-gnu89.c = $(CFLAGS-tst-initializers1-<)
++CFLAGS-tst-initializers1-gnu99.c = $(CFLAGS-tst-initializers1-<)
+ tst-cancel7-ARGS = --command "$(built-program-cmd)"
+ tst-cancelx7-ARGS = $(tst-cancel7-ARGS)
+--- libc/nptl/tst-initializers1-c89.c 1 Jan 1970 00:00:00 -0000
++++ libc/nptl/tst-initializers1-c89.c  9 Jan 2006 23:04:44 -0000       1.1
+@@ -0,0 +1 @@
++#include "tst-initializers1.c"
+--- libc/nptl/tst-initializers1-c99.c 1 Jan 1970 00:00:00 -0000
++++ libc/nptl/tst-initializers1-c99.c  9 Jan 2006 23:04:44 -0000       1.1
+@@ -0,0 +1 @@
++#include "tst-initializers1.c"
+--- libc/nptl/tst-initializers1-gnu89.c 1 Jan 1970 00:00:00 -0000
++++ libc/nptl/tst-initializers1-gnu89.c        9 Jan 2006 23:04:44 -0000       1.1
+@@ -0,0 +1 @@
++#include "tst-initializers1.c"
+--- libc/nptl/tst-initializers1-gnu99.c 1 Jan 1970 00:00:00 -0000
++++ libc/nptl/tst-initializers1-gnu99.c        9 Jan 2006 23:04:44 -0000       1.1
+@@ -0,0 +1 @@
++#include "tst-initializers1.c"
diff --git a/src/patches/glibc/glibc-tst-signal7.patch b/src/patches/glibc/glibc-tst-signal7.patch
new file mode 100644 (file)
index 0000000..dc18755
--- /dev/null
@@ -0,0 +1,78 @@
+2005-12-28  Ulrich Drepper  <drepper@redhat.com>
+
+       * Makefile (tests): Add tst-signal7.
+       * tst-signal7.c: New file.
+
+--- libc/nptl/Makefile 27 Dec 2005 00:53:17 -0000      1.173
++++ libc/nptl/Makefile 28 Dec 2005 20:48:24 -0000      1.174
+@@ -229,7 +229,7 @@ tests = tst-typesizes \
+       tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \
+       tst-flock1 tst-flock2 \
+       tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \
+-      tst-signal6 \
++      tst-signal6 tst-signal7 \
+       tst-exec1 tst-exec2 tst-exec3 tst-exec4 \
+       tst-exit1 tst-exit2 tst-exit3 \
+       tst-stdio1 tst-stdio2 \
+--- libc/nptl/tst-signal7.c 1 Jan 1970 00:00:00 -0000
++++ libc/nptl/tst-signal7.c    28 Dec 2005 20:48:38 -0000      1.1
+@@ -0,0 +1,59 @@
++/* Copyright (C) 2005 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
++
++   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 <errno.h>
++#include <pthreadP.h>
++#include <signal.h>
++#include <stdio.h>
++
++
++static int
++do_test (void)
++{
++  int result = 0;
++
++  errno = 0;
++  if (sigaction (SIGCANCEL, NULL, NULL) == 0)
++    {
++      puts ("sigaction(SIGCANCEL) did not fail");
++      result = 1;
++    }
++  else if (errno != EINVAL)
++    {
++      puts ("sigaction(SIGCANCEL) did not set errno to EINVAL");
++      result = 1;
++    }
++
++  errno = 0;
++  if (sigaction (SIGSETXID, NULL, NULL) == 0)
++    {
++      puts ("sigaction(SIGSETXID) did not fail");
++      result = 1;
++    }
++  else if (errno != EINVAL)
++    {
++      puts ("sigaction(SIGSETXID) did not set errno to EINVAL");
++      result = 1;
++    }
++
++  return result;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-tzdata-update.patch b/src/patches/glibc/glibc-tzdata-update.patch
new file mode 100644 (file)
index 0000000..940abb7
--- /dev/null
@@ -0,0 +1,596 @@
+2005-09-12  Jakub Jelinek  <jakub@redhat.com>
+
+       * fedora/tzdata-update.c: New file.
+
+--- libc/fedora/tzdata-update.c        2004-06-24 14:04:38.000000000 -0400
++++ libc/fedora/tzdata-update.c        2005-09-12 12:10:55.000000000 -0400
+@@ -0,0 +1,589 @@
++#ifdef __sparc__
++register void *__thread_self __asm ("g7");
++#endif
++#define _GNU_SOURCE 1
++#include <errno.h>
++#include <fcntl.h>
++#include <stdlib.h>
++#include <string.h>
++#include <syscall.h>
++#include <unistd.h>
++
++#if defined __i386__
++# define INTERNAL_SYSCALL_DECL(err) do { } while (0)
++# define INTERNAL_SYSCALL(name, err, nr, args...) \
++  ({                                                                        \
++    register unsigned int resultvar;                                        \
++    asm volatile (                                                          \
++    "movl %1, %%eax\n\t"                                                    \
++    "int $0x80\n\t"                                                         \
++    : "=a" (resultvar)                                                              \
++    : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc");                \
++    (int) resultvar; })
++# define INTERNAL_SYSCALL_ERROR_P(val, err) \
++  ((unsigned int) (val) >= 0xfffff001u)
++# define ASMFMT_0()
++# define ASMFMT_1(arg1) \
++      , "b" (arg1)
++# define ASMFMT_2(arg1, arg2) \
++      , "b" (arg1), "c" (arg2)
++# define ASMFMT_3(arg1, arg2, arg3) \
++      , "b" (arg1), "c" (arg2), "d" (arg3)
++#elif defined __x86_64__
++# define INTERNAL_SYSCALL_DECL(err) do { } while (0)
++# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
++  ({                                                                        \
++    unsigned long resultvar;                                                \
++    LOAD_ARGS_##nr (args)                                                   \
++    LOAD_REGS_##nr                                                          \
++    asm volatile (                                                          \
++    "syscall\n\t"                                                           \
++    : "=a" (resultvar)                                                              \
++    : "0" (name) ASM_ARGS_##nr : "memory", "cc", "r11", "cx");                      \
++    (long) resultvar; })
++# define INTERNAL_SYSCALL(name, err, nr, args...) \
++  INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
++# define INTERNAL_SYSCALL_ERROR_P(val, err) \
++  ((unsigned long) (val) >= -4095L)
++# define LOAD_ARGS_0()
++# define LOAD_REGS_0
++# define ASM_ARGS_0
++# define LOAD_ARGS_1(a1)                              \
++  long int __arg1 = (long) (a1);                      \
++  LOAD_ARGS_0 ()
++# define LOAD_REGS_1                                  \
++  register long int _a1 asm ("rdi") = __arg1;         \
++  LOAD_REGS_0
++# define ASM_ARGS_1   ASM_ARGS_0, "r" (_a1)
++# define LOAD_ARGS_2(a1, a2)                          \
++  long int __arg2 = (long) (a2);                      \
++  LOAD_ARGS_1 (a1)
++# define LOAD_REGS_2                                  \
++  register long int _a2 asm ("rsi") = __arg2;         \
++  LOAD_REGS_1
++# define ASM_ARGS_2   ASM_ARGS_1, "r" (_a2)
++# define LOAD_ARGS_3(a1, a2, a3)                      \
++  long int __arg3 = (long) (a3);                      \
++  LOAD_ARGS_2 (a1, a2)
++# define LOAD_REGS_3                                  \
++  register long int _a3 asm ("rdx") = __arg3;         \
++  LOAD_REGS_2
++# define ASM_ARGS_3   ASM_ARGS_2, "r" (_a3)
++#elif defined __powerpc__
++# define INTERNAL_SYSCALL_DECL(err) long int err
++# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
++  ({                                                                  \
++    register long int r0  __asm__ ("r0");                             \
++    register long int r3  __asm__ ("r3");                             \
++    register long int r4  __asm__ ("r4");                             \
++    register long int r5  __asm__ ("r5");                             \
++    register long int r6  __asm__ ("r6");                             \
++    register long int r7  __asm__ ("r7");                             \
++    register long int r8  __asm__ ("r8");                             \
++    LOADARGS_##nr(name, args);                                                \
++    __asm__ __volatile__                                              \
++      ("sc\n\t"                                                               \
++       "mfcr  %0\n\t"                                                 \
++       : "=&r" (r0),                                                  \
++       "=&r" (r3), "=&r" (r4), "=&r" (r5),                            \
++       "=&r" (r6), "=&r" (r7), "=&r" (r8)                             \
++       : ASM_INPUT_##nr                                                       \
++       : "r9", "r10", "r11", "r12",                                   \
++       "cr0", "ctr", "memory");                                       \
++        err = r0;  \
++    (int) r3;  \
++  })
++# define INTERNAL_SYSCALL(name, err, nr, args...)                     \
++  INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
++# define INTERNAL_SYSCALL_ERROR_P(val, err) \
++  ((void) (val), __builtin_expect ((err) & (1 << 28), 0))
++# define LOADARGS_0(name, dummy) \
++      r0 = name
++# define LOADARGS_1(name, __arg1) \
++      long int arg1 = (long int) (__arg1); \
++      LOADARGS_0(name, 0); \
++      r3 = arg1
++# define LOADARGS_2(name, __arg1, __arg2) \
++      long int arg2 = (long int) (__arg2); \
++      LOADARGS_1(name, __arg1); \
++      r4 = arg2
++# define LOADARGS_3(name, __arg1, __arg2, __arg3) \
++      long int arg3 = (long int) (__arg3); \
++      LOADARGS_2(name, __arg1, __arg2); \
++      r5 = arg3
++# define ASM_INPUT_0 "0" (r0)
++# define ASM_INPUT_1 ASM_INPUT_0, "1" (r3)
++# define ASM_INPUT_2 ASM_INPUT_1, "2" (r4)
++# define ASM_INPUT_3 ASM_INPUT_2, "3" (r5)
++#elif defined __ia64__
++# define DO_INLINE_SYSCALL_NCS(name, nr, args...)             \
++    LOAD_ARGS_##nr (args)                                     \
++    register long _r8 asm ("r8");                             \
++    register long _r10 asm ("r10");                           \
++    register long _r15 asm ("r15") = name;                    \
++    long _retval;                                             \
++    LOAD_REGS_##nr                                            \
++    __asm __volatile ("break 0x100000;;"                      \
++                    : "=r" (_r8), "=r" (_r10), "=r" (_r15)    \
++                      ASM_OUTARGS_##nr                        \
++                    : "2" (_r15) ASM_ARGS_##nr                \
++                    : "memory" ASM_CLOBBERS_##nr);            \
++    _retval = _r8;
++# define INTERNAL_SYSCALL_DECL(err) long int err
++# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
++  ({                                                  \
++    DO_INLINE_SYSCALL_NCS (name, nr, args)            \
++    err = _r10;                                               \
++    _retval; })
++# define INTERNAL_SYSCALL(name, err, nr, args...)     \
++  INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
++# define INTERNAL_SYSCALL_ERROR_P(val, err)   (err == -1)
++# define LOAD_ARGS_0()
++# define LOAD_REGS_0
++# define LOAD_ARGS_1(a1)                              \
++  long _arg1 = (long) (a1);                           \
++  LOAD_ARGS_0 ()
++# define LOAD_REGS_1                                  \
++  register long _out0 asm ("out0") = _arg1;           \
++  LOAD_REGS_0
++# define LOAD_ARGS_2(a1, a2)                          \
++  long _arg2 = (long) (a2);                           \
++  LOAD_ARGS_1 (a1)
++# define LOAD_REGS_2                                  \
++  register long _out1 asm ("out1") = _arg2;           \
++  LOAD_REGS_1
++# define LOAD_ARGS_3(a1, a2, a3)                      \
++  long _arg3 = (long) (a3);                           \
++  LOAD_ARGS_2 (a1, a2)
++# define LOAD_REGS_3                                  \
++  register long _out2 asm ("out2") = _arg3;           \
++  LOAD_REGS_2
++# define ASM_OUTARGS_0
++# define ASM_OUTARGS_1        ASM_OUTARGS_0, "=r" (_out0)
++# define ASM_OUTARGS_2        ASM_OUTARGS_1, "=r" (_out1)
++# define ASM_OUTARGS_3        ASM_OUTARGS_2, "=r" (_out2)
++# define ASM_ARGS_0
++# define ASM_ARGS_1   ASM_ARGS_0, "3" (_out0)
++# define ASM_ARGS_2   ASM_ARGS_1, "4" (_out1)
++# define ASM_ARGS_3   ASM_ARGS_2, "5" (_out2)
++# define ASM_CLOBBERS_0       ASM_CLOBBERS_1, "out0"
++# define ASM_CLOBBERS_1       ASM_CLOBBERS_2, "out1"
++# define ASM_CLOBBERS_2       ASM_CLOBBERS_3, "out2"
++# define ASM_CLOBBERS_3       ASM_CLOBBERS_4, "out3"
++# define ASM_CLOBBERS_4       ASM_CLOBBERS_5, "out4"
++# define ASM_CLOBBERS_5       ASM_CLOBBERS_6, "out5"
++# define ASM_CLOBBERS_6_COMMON        , "out6", "out7",                       \
++  /* Non-stacked integer registers, minus r8, r10, r15.  */           \
++  "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18",  \
++  "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27",      \
++  "r28", "r29", "r30", "r31",                                         \
++  /* Predicate registers.  */                                         \
++  "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",   \
++  /* Non-rotating fp registers.  */                                   \
++  "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",   \
++  /* Branch registers.  */                                            \
++  "b6"
++# define ASM_CLOBBERS_6       ASM_CLOBBERS_6_COMMON , "b7"
++#elif defined __s390__
++# define INTERNAL_SYSCALL_DECL(err) do { } while (0)
++# define INTERNAL_SYSCALL_DIRECT(name, err, nr, args...)                    \
++  ({                                                                        \
++    DECLARGS_##nr(args)                                                             \
++    register long _ret asm("2");                                            \
++    asm volatile (                                                          \
++    "svc    %b1\n\t"                                                        \
++    : "=d" (_ret)                                                           \
++    : "i" (__NR_##name) ASMFMT_##nr                                         \
++    : "memory" );                                                           \
++    _ret; })
++# define INTERNAL_SYSCALL_SVC0(name, err, nr, args...)                              \
++  ({                                                                        \
++    DECLARGS_##nr(args)                                                             \
++    register unsigned long _nr asm("1") = (unsigned long)(__NR_##name);             \
++    register long _ret asm("2");                                            \
++    asm volatile (                                                          \
++    "svc    0\n\t"                                                          \
++    : "=d" (_ret)                                                           \
++    : "d" (_nr) ASMFMT_##nr                                                 \
++    : "memory" );                                                           \
++    _ret; })
++# define INTERNAL_SYSCALL(name, err, nr, args...)                           \
++  (((__NR_##name) < 256) ?                                                  \
++    INTERNAL_SYSCALL_DIRECT(name, err, nr, args) :                          \
++    INTERNAL_SYSCALL_SVC0(name, err,nr, args))
++# define INTERNAL_SYSCALL_ERROR_P(val, err)                                 \
++  ((unsigned long) (val) >= -4095UL)
++# define DECLARGS_0()
++# define DECLARGS_1(arg1) \
++      register unsigned long gpr2 asm ("2") = (unsigned long)(arg1);
++# define DECLARGS_2(arg1, arg2) \
++      DECLARGS_1(arg1) \
++      register unsigned long gpr3 asm ("3") = (unsigned long)(arg2);
++# define DECLARGS_3(arg1, arg2, arg3) \
++      DECLARGS_2(arg1, arg2) \
++      register unsigned long gpr4 asm ("4") = (unsigned long)(arg3);
++# define ASMFMT_0
++# define ASMFMT_1 , "0" (gpr2)
++# define ASMFMT_2 , "0" (gpr2), "d" (gpr3)
++# define ASMFMT_3 , "0" (gpr2), "d" (gpr3), "d" (gpr4)
++#elif defined __sparc__
++# ifndef __arch64__
++#  define __INTERNAL_SYSCALL_STRING                                   \
++      "ta     0x10;"                                                  \
++      "bcs,a  1f;"                                                    \
++      " sub   %%g0, %%o0, %%o0;"                                      \
++      "1:"
++#  define __SYSCALL_CLOBBERS "g2", "g3", "g4", "g5", "g6",            \
++      "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",                 \
++      "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",           \
++      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",         \
++      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",         \
++      "cc", "memory"
++# else
++#  define __INTERNAL_SYSCALL_STRING                                   \
++      "ta     0x6d;"                                                  \
++      "bcs,a,pt %%xcc, 1f;"                                           \
++      " sub   %%g0, %%o0, %%o0;"                                      \
++      "1:"
++#  define __SYSCALL_CLOBBERS "g2", "g3", "g4", "g5", "g6",            \
++      "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",                 \
++      "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",           \
++      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",         \
++      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",         \
++      "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",         \
++      "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",         \
++      "cc", "memory"
++# endif
++#define INTERNAL_SYSCALL_DECL(err) do { } while (0)
++#define INTERNAL_SYSCALL(name, err, nr, args...) \
++  inline_syscall##nr(__INTERNAL_SYSCALL_STRING, __NR_##name, args)
++#define INTERNAL_SYSCALL_ERROR_P(val, err) \
++  ((unsigned long) (val) >= -515L)
++# define inline_syscall0(string,name,dummy...)                                \
++({                                                                    \
++      register long __o0 __asm__ ("o0");                              \
++      register long __g1 __asm__ ("g1") = name;                       \
++      __asm __volatile (string : "=r" (__g1), "=r" (__o0) :           \
++                        "0" (__g1) :                                  \
++                        __SYSCALL_CLOBBERS);                          \
++      __o0;                                                           \
++})
++# define inline_syscall1(string,name,arg1)                            \
++({                                                                    \
++      register long __o0 __asm__ ("o0") = (long)(arg1);               \
++      register long __g1 __asm__ ("g1") = name;                       \
++      __asm __volatile (string : "=r" (__g1), "=r" (__o0) :           \
++                        "0" (__g1), "1" (__o0) :                      \
++                        __SYSCALL_CLOBBERS);                          \
++      __o0;                                                           \
++})
++# define inline_syscall2(string,name,arg1,arg2)                               \
++({                                                                    \
++      register long __o0 __asm__ ("o0") = (long)(arg1);               \
++      register long __o1 __asm__ ("o1") = (long)(arg2);               \
++      register long __g1 __asm__ ("g1") = name;                       \
++      __asm __volatile (string : "=r" (__g1), "=r" (__o0) :           \
++                        "0" (__g1), "1" (__o0), "r" (__o1) :          \
++                        __SYSCALL_CLOBBERS);                          \
++      __o0;                                                           \
++})
++# define inline_syscall3(string,name,arg1,arg2,arg3)                  \
++({                                                                    \
++      register long __o0 __asm__ ("o0") = (long)(arg1);               \
++      register long __o1 __asm__ ("o1") = (long)(arg2);               \
++      register long __o2 __asm__ ("o2") = (long)(arg3);               \
++      register long __g1 __asm__ ("g1") = name;                       \
++      __asm __volatile (string : "=r" (__g1), "=r" (__o0) :           \
++                        "0" (__g1), "1" (__o0), "r" (__o1),           \
++                        "r" (__o2) :                                  \
++                        __SYSCALL_CLOBBERS);                          \
++      __o0;                                                           \
++})
++#elif defined __alpha__
++# define INTERNAL_SYSCALL(name, err_out, nr, args...) \
++      INTERNAL_SYSCALL1(name, err_out, nr, args)
++# define INTERNAL_SYSCALL1(name, err_out, nr, args...)        \
++      INTERNAL_SYSCALL_NCS(__NR_##name, err_out, nr, args)
++# define INTERNAL_SYSCALL_NCS(name, err_out, nr, args...) \
++({                                                    \
++      long _sc_ret, _sc_err;                          \
++      inline_syscall##nr(name, args);                 \
++      err_out = _sc_err;                              \
++      _sc_ret;                                        \
++})
++# define INTERNAL_SYSCALL_DECL(err)           long int err
++# define INTERNAL_SYSCALL_ERROR_P(val, err)   err
++# define inline_syscall_clobbers                      \
++      "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", \
++      "$22", "$23", "$24", "$25", "$27", "$28", "memory"
++# define inline_syscall_r0_asm
++# define inline_syscall_r0_out_constraint     "=v"
++# define inline_syscall0(name, args...)                               \
++{                                                             \
++      register long _sc_0 inline_syscall_r0_asm;              \
++      register long _sc_19 __asm__("$19");                    \
++                                                              \
++      _sc_0 = name;                                           \
++      __asm__ __volatile__                                    \
++        ("callsys # %0 %1 <= %2"                              \
++         : inline_syscall_r0_out_constraint (_sc_0),          \
++           "=r"(_sc_19)                                       \
++         : "0"(_sc_0)                                         \
++         : inline_syscall_clobbers,                           \
++           "$16", "$17", "$18", "$20", "$21");                \
++      _sc_ret = _sc_0, _sc_err = _sc_19;                      \
++}
++# define inline_syscall1(name,arg1)                           \
++{                                                             \
++      register long _sc_0 inline_syscall_r0_asm;              \
++      register long _sc_16 __asm__("$16");                    \
++      register long _sc_19 __asm__("$19");                    \
++                                                              \
++      _sc_0 = name;                                           \
++      _sc_16 = (long) (arg1);                                 \
++      __asm__ __volatile__                                    \
++        ("callsys # %0 %1 <= %2 %3"                           \
++         : inline_syscall_r0_out_constraint (_sc_0),          \
++           "=r"(_sc_19), "=r"(_sc_16)                         \
++         : "0"(_sc_0), "2"(_sc_16)                            \
++         : inline_syscall_clobbers,                           \
++           "$17", "$18", "$20", "$21");                       \
++      _sc_ret = _sc_0, _sc_err = _sc_19;                      \
++}
++# define inline_syscall2(name,arg1,arg2)                      \
++{                                                             \
++      register long _sc_0 inline_syscall_r0_asm;              \
++      register long _sc_16 __asm__("$16");                    \
++      register long _sc_17 __asm__("$17");                    \
++      register long _sc_19 __asm__("$19");                    \
++                                                              \
++      _sc_0 = name;                                           \
++      _sc_16 = (long) (arg1);                                 \
++      _sc_17 = (long) (arg2);                                 \
++      __asm__ __volatile__                                    \
++        ("callsys # %0 %1 <= %2 %3 %4"                        \
++         : inline_syscall_r0_out_constraint (_sc_0),          \
++           "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17)           \
++         : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17)               \
++         : inline_syscall_clobbers,                           \
++           "$18", "$20", "$21");                              \
++      _sc_ret = _sc_0, _sc_err = _sc_19;                      \
++}
++# define inline_syscall3(name,arg1,arg2,arg3)                 \
++{                                                             \
++      register long _sc_0 inline_syscall_r0_asm;              \
++      register long _sc_16 __asm__("$16");                    \
++      register long _sc_17 __asm__("$17");                    \
++      register long _sc_18 __asm__("$18");                    \
++      register long _sc_19 __asm__("$19");                    \
++                                                              \
++      _sc_0 = name;                                           \
++      _sc_16 = (long) (arg1);                                 \
++      _sc_17 = (long) (arg2);                                 \
++      _sc_18 = (long) (arg3);                                 \
++      __asm__ __volatile__                                    \
++        ("callsys # %0 %1 <= %2 %3 %4 %5"                     \
++         : inline_syscall_r0_out_constraint (_sc_0),          \
++           "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),          \
++           "=r"(_sc_18)                                       \
++         : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),              \
++           "4"(_sc_18)                                        \
++         : inline_syscall_clobbers, "$20", "$21");            \
++      _sc_ret = _sc_0, _sc_err = _sc_19;                      \
++}
++#endif
++
++char buffer[32768], data[32768];
++size_t datasize;
++char zonename[1024];
++
++ssize_t
++readall (int fd, void *buf, size_t len)
++{
++  INTERNAL_SYSCALL_DECL (err);
++  size_t n = len;
++  ssize_t ret;
++  do
++    {
++      ret = INTERNAL_SYSCALL (read, err, 3, fd, buf, n);
++      if (INTERNAL_SYSCALL_ERROR_P (ret, err))
++      {
++        ret = -1;
++        break;
++      }
++      else if (ret == 0)
++      break;
++      buf = (char *) buf + ret;
++      n -= ret;
++    }
++  while (n > 0);
++  return ret < 0 ? ret : (ssize_t) (len - n);
++}
++
++ssize_t
++writeall (int fd, const void *buf, size_t len)
++{
++  INTERNAL_SYSCALL_DECL (err);
++  size_t n = len;
++  ssize_t ret;
++  do
++    {
++      ret = INTERNAL_SYSCALL (write, err, 3, fd, buf, n);
++      if (INTERNAL_SYSCALL_ERROR_P (ret, err))
++      {
++        ret = -1;
++        break;
++      }
++      else if (ret == 0)
++      break;
++      buf = (const char *) buf + ret;
++      n -= ret;
++    }
++  while (n > 0);
++  return ret < 0 ? ret : (ssize_t) (len - n);
++}
++
++void
++update (const char *filename)
++{
++  INTERNAL_SYSCALL_DECL (err);
++  long int fd = INTERNAL_SYSCALL (open, err, 2, filename, O_RDONLY);
++  if (INTERNAL_SYSCALL_ERROR_P (fd, err))
++    return;
++  ssize_t ret = readall (fd, buffer, sizeof (buffer));
++  INTERNAL_SYSCALL (close, err, 1, fd);
++  if (ret <= 0 || (size_t) ret == sizeof (buffer))
++    return;
++  /* Don't update the file unnecessarily.  */
++  if ((size_t) ret == datasize && memcmp (buffer, data, datasize) == 0)
++    return;
++  size_t len = strlen (filename);
++  char tempfilename[len + sizeof (".tzupdate")];
++  memcpy (tempfilename, filename, len);
++  memcpy (tempfilename + len, ".tzupdate", sizeof (".tzupdate"));
++
++  fd = INTERNAL_SYSCALL (open, err, 3, tempfilename, O_WRONLY | O_CREAT | O_EXCL, 0600);
++  if (INTERNAL_SYSCALL_ERROR_P (fd, err))
++    return;
++  if (writeall (fd, data, datasize) != datasize)
++    {
++clean_up:
++      INTERNAL_SYSCALL (unlink, err, 1, tempfilename);
++      INTERNAL_SYSCALL (close, err, 1, fd);
++      return;
++    }
++  long int sret;
++  sret = INTERNAL_SYSCALL (fchmod, err, 2, fd, 0644);
++  if (INTERNAL_SYSCALL_ERROR_P (sret, err))
++    goto clean_up;
++  INTERNAL_SYSCALL (close, err, 1, fd);
++
++  sret = INTERNAL_SYSCALL (rename, err, 2, tempfilename, filename);
++  if (INTERNAL_SYSCALL_ERROR_P (sret, err))
++    INTERNAL_SYSCALL (unlink, err, 1, tempfilename);
++}
++
++int
++main (int argc, char **argv)
++{
++  INTERNAL_SYSCALL_DECL (err);
++  long int fd = INTERNAL_SYSCALL (open, err, 2, "/etc/sysconfig/clock", O_RDONLY);
++  if (INTERNAL_SYSCALL_ERROR_P (fd, err))
++    return 0;
++  ssize_t ret = readall (fd, buffer, sizeof (buffer) - 1);
++  INTERNAL_SYSCALL (close, err, 1, fd);
++  if (ret <= 0 || (size_t) ret == sizeof (buffer) - 1)
++    return 0;
++  char *p = buffer;
++  while (p != NULL)
++    {
++      while (*p == ' ' || *p == '\t') p++;
++      if (memcmp (p, "ZONE", 4) == 0)
++      {
++        p += 4;
++        while (*p == ' ' || *p == '\t') p++;
++        if (*p == '=')
++          {
++            p++;
++            while (*p == ' ' || *p == '\t') p++;
++            if (*p == '"') p++;
++            char *q = p;
++            while (strchr (" \t\n\"", *p) == NULL) p++;
++            const char path[] = "/usr/share/zoneinfo/";
++            if (p - q >= sizeof (zonename) - sizeof (path))
++              return 0;
++            memcpy (zonename, path, sizeof (path) - 1);
++            memcpy (zonename + sizeof (path) - 1, q, p - q);
++            break;
++          }
++      }
++      p = strchr (p, '\n');
++      if (p) p++;
++    }
++  if (*zonename == '\0')
++    return 0;
++  fd = INTERNAL_SYSCALL (open, err, 2, zonename, O_RDONLY);
++  if (INTERNAL_SYSCALL_ERROR_P (fd, err))
++    return 0;
++  ret = readall (fd, data, sizeof (data));
++  INTERNAL_SYSCALL (close, err, 1, fd);
++  if (ret <= 0 || (size_t) ret == sizeof (data))
++    return 0;
++  datasize = (size_t) ret;
++  update ("/etc/localtime");
++  update ("/var/spool/postfix/etc/localtime");
++  return 0;
++}
++
++int __libc_multiple_threads __attribute__((nocommon));
++int __libc_enable_asynccancel (void) { return 0; }
++void __libc_disable_asynccancel (int x) { }
++void __libc_csu_init (void) { }
++void __libc_csu_fini (void) { }
++pid_t __fork (void) { return -1; }
++char thr_buf[65536];
++
++#ifndef __powerpc__
++int __libc_start_main (int (*main) (int argc, char **argv),
++                     int argc, char **argv,
++                     void (*init) (void), void (*fini) (void),
++                     void (*rtld_fini) (void), void * stack_end)
++#else
++struct startup_info
++{
++  void *sda_base;
++  int (*main) (int, char **, char **, void *);
++  int (*init) (int, char **, char **, void *);
++  void (*fini) (void);
++};
++
++int __libc_start_main (int argc, char **argv, char **ev,
++                     void *auxvec, void (*rtld_fini) (void),
++                     struct startup_info *stinfo,
++                     char **stack_on_entry)
++#endif
++{
++#if defined __ia64__ || defined __powerpc64__
++  register void *r13 __asm ("r13") = thr_buf + 32768;
++  __asm ("" : : "r" (r13));
++#elif defined __sparc__
++  register void *g6 __asm ("g6") = thr_buf + 32768;
++  __thread_self = thr_buf + 32768;
++  __asm ("" : : "r" (g6), "r" (__thread_self));
++#elif defined __s390__ && !defined __s390x__
++  __asm ("sar %%a0,%0" : : "d" (thr_buf + 32768));
++#elif defined __s390x__
++  __asm ("sar %%a1,%0; srlg 0,%0,32; sar %%a0,0" : : "d" (thr_buf + 32768) : "0");
++#elif defined __powerpc__ && !defined __powerpc64__
++  register void *r2 __asm ("r2") = thr_buf + 32768;
++  __asm ("" : : "r" (r2));
++#endif
++#ifdef __powerpc__
++  argc = (long)*stack_on_entry;
++  argv = stack_on_entry + 1;
++#endif
++  long ret = main (argc, argv);
++  INTERNAL_SYSCALL_DECL (err);
++  INTERNAL_SYSCALL (exit, err, 1, ret);
++  return 110;
++}
diff --git a/src/patches/glibc/glibc-wcstol-internal.patch b/src/patches/glibc/glibc-wcstol-internal.patch
new file mode 100644 (file)
index 0000000..3910f1c
--- /dev/null
@@ -0,0 +1,43 @@
+2006-03-16  Roland McGrath  <roland@redhat.com>
+
+       * wcsmbs/wchar.h (__wcstol_internal, __wcstoul_internal): Declare these
+        only when we will use them, under [__OPTIMIZE__ && __GNUC__ >= 2].
+       (__wcstoll_internal, __wcstoull_internal_defined): Likewise.
+
+--- libc/wcsmbs/wchar.h        14 Jan 2006 20:14:36 -0000      1.62
++++ libc/wcsmbs/wchar.h        16 Mar 2006 22:10:58 -0000      1.63
+@@ -507,26 +507,30 @@ extern long double __wcstold_internal (_
+                                      wchar_t **__restrict __endptr,
+                                      int __group) __THROW;
+-#ifndef __wcstol_internal_defined
++#if !defined __wcstol_internal_defined \
++    && defined __OPTIMIZE__ && __GNUC__ >= 2
+ extern long int __wcstol_internal (__const wchar_t *__restrict __nptr,
+                                  wchar_t **__restrict __endptr,
+                                  int __base, int __group) __THROW;
+ # define __wcstol_internal_defined    1
+ #endif
+-#ifndef __wcstoul_internal_defined
++#if !defined __wcstoul_internal_defined \
++    && defined __OPTIMIZE__ && __GNUC__ >= 2
+ extern unsigned long int __wcstoul_internal (__const wchar_t *__restrict __npt,
+                                            wchar_t **__restrict __endptr,
+                                            int __base, int __group) __THROW;
+ # define __wcstoul_internal_defined   1
+ #endif
+-#ifndef __wcstoll_internal_defined
++#if !defined __wcstoll_internal_defined \
++    && defined __OPTIMIZE__ && __GNUC__ >= 2
+ __extension__
+ extern long long int __wcstoll_internal (__const wchar_t *__restrict __nptr,
+                                        wchar_t **__restrict __endptr,
+                                        int __base, int __group) __THROW;
+ # define __wcstoll_internal_defined   1
+ #endif
+-#ifndef __wcstoull_internal_defined
++#if !defined __wcstoull_internal_defined \
++    && defined __OPTIMIZE__ && __GNUC__ >= 2
+ __extension__
+ extern unsigned long long int __wcstoull_internal (__const wchar_t *
+                                                  __restrict __nptr,
diff --git a/src/patches/glibc/glibc-x86_64-gas-workaround.patch b/src/patches/glibc/glibc-x86_64-gas-workaround.patch
new file mode 100644 (file)
index 0000000..e633305
--- /dev/null
@@ -0,0 +1,31 @@
+2005-07-06  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/x86_64/__longjmp.S (__longjmp): Use 3 instead of %rbx
+       and 5 instead of %rdi in cfi directives to workaround buggy assembler.
+
+--- libc/sysdeps/unix/sysv/linux/x86_64/setcontext.S.jj        2004-01-22 09:17:42.000000000 +0100
++++ libc/sysdeps/unix/sysv/linux/x86_64/setcontext.S   2005-07-06 12:00:02.000000000 +0200
+@@ -59,8 +59,8 @@ ENTRY(__setcontext)
+       /* Load the new stack pointer, the preserved registers and
+          registers used for passing args.  */
+-      cfi_def_cfa(%rdi, 0)
+-      cfi_offset(%rbx,oRBX)
++      cfi_def_cfa(5, 0) /* %rdi; workaround for buggy assembler.  */
++      cfi_offset(3,oRBX) /* %rbx; workaround for buggy assembler.  */
+       cfi_offset(%rbp,oRBP)
+       cfi_offset(%r12,oR12)
+       cfi_offset(%r13,oR13)
+--- libc/sysdeps/x86_64/__longjmp.S.jj 2004-01-11 13:23:01.000000000 +0100
++++ libc/sysdeps/x86_64/__longjmp.S    2005-07-06 12:01:13.000000000 +0200
+@@ -28,8 +28,8 @@
+ ENTRY(__longjmp)
+       /* Restore registers.  */
+       /* We add unwind information for the target here.  */
+-      cfi_def_cfa(%rdi, 0)
+-      cfi_offset(%rbx,JB_RBX*8)
++      cfi_def_cfa(5, 0) /* %rdi; workaround for buggy assembler.  */
++      cfi_offset(3,JB_RBX*8) /* %rbx; workaround for buggy assembler.  */
+       cfi_offset(%rbp,JB_RBP*8)
+       cfi_offset(%r12,JB_R12*8)
+       cfi_offset(%r13,JB_R13*8)
diff --git a/src/patches/glibc/glibc-x86_64-pthread_once-align.patch b/src/patches/glibc/glibc-x86_64-pthread_once-align.patch
new file mode 100644 (file)
index 0000000..8e218bb
--- /dev/null
@@ -0,0 +1,155 @@
+2005-10-14  Jakub Jelinek  <jakub@redhat.com>
+            Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Fix stack
+       alignment in callback function.
+       * Makefile: Add rules to build and run tst-align3.
+       * tst-align3.c: New file.
+
+--- libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S    2003-07-01 19:01:44.000000000 +0200
++++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S    2005-10-14 21:22:58.000000000 +0200
+@@ -82,9 +82,11 @@ __pthread_once:
+       /* Preserve the pointer to the control variable.  */
+ 3:    pushq   %rdi
+ .Lpush_rdi:
++      pushq   %rdi
++.Lpush_rdi2:
+ .LcleanupSTART:
+-      callq   *8(%rsp)
++      callq   *16(%rsp)
+ .LcleanupEND:
+       /* Get the control variable address back.  */
+@@ -95,6 +97,9 @@ __pthread_once:
+       LOCK
+       incl    (%rdi)
++      addq    $8, %rsp
++.Ladd1:
++
+       /* Wake up all other threads.  */
+       movl    $0x7fffffff, %edx
+       movl    $FUTEX_WAKE, %esi
+@@ -102,7 +107,7 @@ __pthread_once:
+       syscall
+ 4:    addq    $8, %rsp
+-.Ladd:
++.Ladd2:
+       xorq    %rax, %rax
+       retq
+@@ -220,20 +225,28 @@ clear_once_control:
+       .byte   14                              # DW_CFA_def_cfa_offset
+       .uleb128 24
+       .byte   4                               # DW_CFA_advance_loc4
+-      .long   .Lpop_rdi-.Lpush_rdi
++      .long   .Lpush_rdi2-.Lpush_rdi
++      .byte   14                              # DW_CFA_def_cfa_offset
++      .uleb128 32
++      .byte   4                               # DW_CFA_advance_loc4
++      .long   .Lpop_rdi-.Lpush_rdi2
++      .byte   14                              # DW_CFA_def_cfa_offset
++      .uleb128 24
++      .byte   4                               # DW_CFA_advance_loc4
++      .long   .Ladd1-.Lpop_rdi
+       .byte   14                              # DW_CFA_def_cfa_offset
+       .uleb128 16
+       .byte   4                               # DW_CFA_advance_loc4
+-      .long   .Ladd-.Lpop_rdi
++      .long   .Ladd2-.Ladd1
+       .byte   14                              # DW_CFA_def_cfa_offset
+       .uleb128 8
+       .byte   4                               # DW_CFA_advance_loc4
+-      .long   clear_once_control-.Ladd
++      .long   clear_once_control-.Ladd2
+       .byte   14                              # DW_CFA_def_cfa_offset
+-      .uleb128 24
++      .uleb128 32
+ #if 0
+       .byte   4                               # DW_CFA_advance_loc4
+-      .long   .Lpop_rdi2-clear_once_control
++      .long   .Lpop_rdi3-clear_once_control
+       .byte   14                              # DW_CFA_def_cfa_offset
+       .uleb128 16
+ #endif
+--- libc/nptl/Makefile 11 Jul 2005 16:40:21 -0000      1.169
++++ libc/nptl/Makefile 14 Oct 2005 18:50:50 -0000      1.170
+@@ -205,7 +205,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 \
+       tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
+       tst-sem8 tst-sem9 \
+       tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
+-      tst-align tst-align2 \
++      tst-align tst-align2 tst-align3 \
+       tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \
+       tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
+       tst-raise1 \
+@@ -412,6 +412,7 @@ CFLAGS-tst-cleanupx4.c += -fexceptions
+ CFLAGS-tst-oncex3.c += -fexceptions
+ CFLAGS-tst-oncex4.c += -fexceptions
+ CFLAGS-tst-align.c += $(stack-align-test-flags)
++CFLAGS-tst-align3.c += $(stack-align-test-flags)
+ CFLAGS-tst-initializers1.c += -W -Wall -Werror
+ tst-cancel7-ARGS = --command "$(built-program-cmd)"
+--- libc/nptl/tst-align3.c 1 Jan 1970 00:00:00 -0000
++++ libc/nptl/tst-align3.c     14 Oct 2005 18:49:29 -0000      1.1
+@@ -0,0 +1,57 @@
++/* Copyright (C) 2005 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Jakub Jelinek <jakub@redhat.com>, 2005.
++
++   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 <pthread.h>
++#include <stdbool.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <tst-stack-align.h>
++
++static bool ok = true;
++static pthread_once_t once = PTHREAD_ONCE_INIT;
++
++static void
++once_test (void)
++{
++  puts ("in once_test");
++
++  if (TEST_STACK_ALIGN ())
++    ok = false;
++}
++
++static int
++do_test (void)
++{
++  puts ("in main");
++
++  if (TEST_STACK_ALIGN ())
++    ok = false;
++
++  if (pthread_once (&once, once_test))
++    {
++      puts ("pthread once failed");
++      return 1;
++    }
++
++  return ok ? 0 : 1;
++}
++
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
diff --git a/src/patches/glibc/glibc-xtrace-options.patch b/src/patches/glibc/glibc-xtrace-options.patch
new file mode 100644 (file)
index 0000000..7d3e420
--- /dev/null
@@ -0,0 +1,17 @@
+2005-09-17  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1053]
+       * debug/xtrace.sh: Add missing escape character in -? match.
+       Patch by Peter Breitenlohner <peb@mppmu.mpg.de>.
+
+--- libc/debug/xtrace.sh       12 Jan 2005 23:39:52 -0000      1.14
++++ libc/debug/xtrace.sh       17 Sep 2005 17:30:44 -0000      1.15
+@@ -107,7 +107,7 @@ while test $# -gt 0; do
+   --d=* | --da=* | --dat=* | --data=*)
+     data=${1##*=}
+     ;;
+-  -? | --h | --he | --hel | --help)
++  -\? | --h | --he | --hel | --help)
+     do_help
+     ;;
+   -V | --v | --ve | --ver | --vers | --versi | --versio | --version)