From fd9d43a95f6398a0089be28e2c726815b7ab1b9d Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Fri, 8 Oct 2010 10:12:02 +0200 Subject: [PATCH] Import patchset for glibc. --- lfs/glibc | 4 + src/patches/glibc/glibc-2.3.6-fedora.patch | 2618 ++++++++ src/patches/glibc/glibc-DT_GNU_HASH.patch | 34 + src/patches/glibc/glibc-MALLOC_CHECK_.patch | 18 + src/patches/glibc/glibc-Wundef.patch | 38 + src/patches/glibc/glibc-aio-rh171968.patch | 584 ++ src/patches/glibc/glibc-argp-key.patch | 26 + src/patches/glibc/glibc-argp-vasprintf.patch | 39 + src/patches/glibc/glibc-argp_usage-NTH.patch | 16 + src/patches/glibc/glibc-asctime.patch | 191 + src/patches/glibc/glibc-bindresvport.patch | 37 + src/patches/glibc/glibc-byteswap.patch | 44 + src/patches/glibc/glibc-bz1051.patch | 155 + src/patches/glibc/glibc-bz1078.patch | 151 + src/patches/glibc/glibc-bz1201.patch | 17 + src/patches/glibc/glibc-bz1228.patch | 40 + src/patches/glibc/glibc-bz1230.patch | 114 + src/patches/glibc/glibc-bz1346.patch | 55 + src/patches/glibc/glibc-bz1548.patch | 18 + src/patches/glibc/glibc-bz1566.patch | 19 + src/patches/glibc/glibc-bz1579.patch | 17 + src/patches/glibc/glibc-bz1774.patch | 43 + src/patches/glibc/glibc-bz1913.patch | 26 + src/patches/glibc/glibc-bz1920.patch | 52 + src/patches/glibc/glibc-bz1925.patch | 16 + src/patches/glibc/glibc-bz1951.patch | 253 + src/patches/glibc/glibc-bz1952.patch | 65 + src/patches/glibc/glibc-bz1955.patch | 17 + src/patches/glibc/glibc-bz1962.patch | 67 + src/patches/glibc/glibc-bz1978.patch | 55 + src/patches/glibc/glibc-bz2013.patch | 81 + src/patches/glibc/glibc-bz2066.patch | 20 + src/patches/glibc/glibc-bz2072.patch | 84 + src/patches/glibc/glibc-bz2080.patch | 19 + src/patches/glibc/glibc-bz2126.patch | 118 + src/patches/glibc/glibc-bz2153.patch | 281 + src/patches/glibc/glibc-bz2173.patch | 150 + src/patches/glibc/glibc-bz2182.patch | 46 + src/patches/glibc/glibc-bz2226.patch | 17 + src/patches/glibc/glibc-bz2268.patch | 25 + src/patches/glibc/glibc-bz2415.patch | 22 + src/patches/glibc/glibc-bz2418.patch | 25 + src/patches/glibc/glibc-bz2420.patch | 131 + src/patches/glibc/glibc-bz2451.patch | 147 + src/patches/glibc/glibc-bz2498.patch | 44 + src/patches/glibc/glibc-bz2499.patch | 97 + src/patches/glibc/glibc-bz2501.patch | 76 + src/patches/glibc/glibc-bz2502.patch | 17 + src/patches/glibc/glibc-bz2509.patch | 89 + src/patches/glibc/glibc-bz2571.patch | 53 + src/patches/glibc/glibc-bz2592.patch | 447 ++ src/patches/glibc/glibc-bz2632.patch | 17 + src/patches/glibc/glibc-bz2644.patch | 35 + src/patches/glibc/glibc-bz2680.patch | 17 + src/patches/glibc/glibc-bz2684.patch | 39 + src/patches/glibc/glibc-bz2703.patch | 113 + src/patches/glibc/glibc-bz2766.patch | 111 + src/patches/glibc/glibc-bz2775.patch | 32 + src/patches/glibc/glibc-bz2792.patch | 32 + src/patches/glibc/glibc-bz2821.patch | 55 + src/patches/glibc/glibc-bz2841.patch | 20 + src/patches/glibc/glibc-bz2843.patch | 359 ++ src/patches/glibc/glibc-bz2892.patch | 19 + src/patches/glibc/glibc-bz2908.patch | 93 + src/patches/glibc/glibc-bz2998.patch | 19 + src/patches/glibc/glibc-bz3123.patch | 297 + src/patches/glibc/glibc-bz3124.patch | 241 + src/patches/glibc/glibc-bz3155.patch | 27 + src/patches/glibc/glibc-bz3253.patch | 271 + src/patches/glibc/glibc-bz3406.patch | 27 + src/patches/glibc/glibc-bz3451.patch | 62 + src/patches/glibc/glibc-bz3458.patch | 57 + src/patches/glibc/glibc-bz3842.patch | 30 + src/patches/glibc/glibc-bz3855.patch | 204 + src/patches/glibc/glibc-bz3902.patch | 71 + src/patches/glibc/glibc-bz394.patch | 40 + src/patches/glibc/glibc-bz3944.patch | 109 + src/patches/glibc/glibc-bz3957.patch | 189 + src/patches/glibc/glibc-bz4070.patch | 207 + src/patches/glibc/glibc-bz4074.patch | 29 + src/patches/glibc/glibc-bz4101.patch | 148 + src/patches/glibc/glibc-bz4130.patch | 32 + src/patches/glibc/glibc-bz4344.patch | 34 + src/patches/glibc/glibc-bz4349.patch | 278 + src/patches/glibc/glibc-bz4364.patch | 18 + src/patches/glibc/glibc-bz4405.patch | 17 + src/patches/glibc/glibc-bz4438.patch | 81 + src/patches/glibc/glibc-bz4439.patch | 144 + src/patches/glibc/glibc-bz4514.patch | 79 + src/patches/glibc/glibc-bz4586.patch | 50 + src/patches/glibc/glibc-bz4702.patch | 32 + src/patches/glibc/glibc-bz4745.patch | 169 + src/patches/glibc/glibc-bz4776.patch | 86 + src/patches/glibc/glibc-bz4813.patch | 18 + src/patches/glibc/glibc-bz4858.patch | 48 + src/patches/glibc/glibc-bz524.patch | 18 + src/patches/glibc/glibc-bz5854.patch | 18 + src/patches/glibc/glibc-bz644.patch | 171 + src/patches/glibc/glibc-bz6461.patch | 39 + src/patches/glibc/glibc-bz6719.patch | 69 + src/patches/glibc/glibc-bz714.patch | 107 + src/patches/glibc/glibc-bz968.patch | 29 + src/patches/glibc/glibc-coverity.patch | 1608 +++++ src/patches/glibc/glibc-coverity2.patch | 854 +++ src/patches/glibc/glibc-csqrt.patch | 69 + src/patches/glibc/glibc-ctermid.patch | 15 + src/patches/glibc/glibc-do_ypcall.patch | 16 + src/patches/glibc/glibc-doc-fixes.patch | 103 + src/patches/glibc/glibc-dst-req-static.patch | 58 + src/patches/glibc/glibc-dtv-is_static.patch | 642 ++ .../glibc/glibc-elf64-filebuf-size.patch | 35 + src/patches/glibc/glibc-euidaccess.patch | 70 + src/patches/glibc/glibc-fgets-1.patch | 112 + src/patches/glibc/glibc-gai-leak.patch | 36 + .../glibc/glibc-gconv-cache-memleak.patch | 16 + src/patches/glibc/glibc-getconf-a.patch | 81 + src/patches/glibc/glibc-getdelim-trunc.patch | 30 + .../glibc/glibc-getent-gethostbyaddr.patch | 19 + src/patches/glibc/glibc-getent-leak.patch | 15 + src/patches/glibc/glibc-glob-getlogin_r.patch | 17 + src/patches/glibc/glibc-hwcap-mask.patch | 89 + src/patches/glibc/glibc-hypotf.patch | 51 + .../glibc/glibc-i386-futex-timed-wait.patch | 92 + src/patches/glibc/glibc-i386-nosegneg.patch | 255 + .../glibc/glibc-i386-timedrwlock.patch | 97 + src/patches/glibc/glibc-i686-memset.patch | 31 + src/patches/glibc/glibc-ia64-lib64.patch | 92 + src/patches/glibc/glibc-ia64-libm-error.patch | 35 + src/patches/glibc/glibc-ia64-mcount.patch | 30 + .../glibc/glibc-ia64-post-upgrade-hack.patch | 61 + src/patches/glibc/glibc-ia64-shmatt_t.patch | 25 + src/patches/glibc/glibc-innetgr-leak.patch | 35 + .../glibc/glibc-innetgr-thread-safety.patch | 411 ++ .../glibc/glibc-ld-library-path-DST.patch | 33 + .../glibc/glibc-ld_debug-conflicts.patch | 19 + .../glibc/glibc-ldconfig-prelink.patch | 28 + src/patches/glibc/glibc-lddlibc4.patch | 13 + .../glibc/glibc-linuxthreads-atomic_h.patch | 66 + .../glibc/glibc-loadarchive-leak.patch | 20 + .../glibc/glibc-localealias-leak.patch | 33 + src/patches/glibc/glibc-madvise-hidden.patch | 24 + src/patches/glibc/glibc-nan.patch | 24 + src/patches/glibc/glibc-nis+-batch.patch | 5381 +++++++++++++++++ src/patches/glibc/glibc-nis+-batch2.patch | 52 + src/patches/glibc/glibc-nis+-findserver.patch | 193 + src/patches/glibc/glibc-nis+-getenv.patch | 32 + src/patches/glibc/glibc-nis+-getnames.patch | 338 ++ src/patches/glibc/glibc-nis+-leaks.patch | 373 ++ src/patches/glibc/glibc-nis+-leaks2.patch | 15 + src/patches/glibc/glibc-nis+-parent.patch | 1882 ++++++ src/patches/glibc/glibc-nis+.patch | 4601 ++++++++++++++ .../glibc/glibc-nis-getservbyname.patch | 16 + src/patches/glibc/glibc-nis-publickey.patch | 16 + src/patches/glibc/glibc-nis_leaf_of_r-0.patch | 15 + src/patches/glibc/glibc-nonnull.patch | 20 + .../glibc/glibc-nptl-cancel-init.patch | 18 + src/patches/glibc/glibc-nptl-check.patch | 48 + .../glibc/glibc-nptl-fork-cancel.patch | 57 + .../glibc/glibc-nptl-fork-getpid.patch | 150 + src/patches/glibc/glibc-nptl-futex-wait.patch | 27 + src/patches/glibc/glibc-nptl-setxid-2.patch | 213 + src/patches/glibc/glibc-nptl-setxid.patch | 263 + src/patches/glibc/glibc-nscd-EINTR.patch | 177 + .../glibc/glibc-nscd-LFS-logging.patch | 15 + .../glibc-nscd-SIGHUP-disabled-cache.patch | 27 + src/patches/glibc/glibc-nscd-SIGHUP.patch | 81 + .../glibc/glibc-nscd-addinitgroups.patch | 39 + .../glibc/glibc-nscd-auto-propagate.patch | 197 + src/patches/glibc/glibc-nscd-db-checker.patch | 298 + .../glibc/glibc-nscd-debug-verbose.patch | 52 + src/patches/glibc/glibc-nscd-fallocate.patch | 36 + .../glibc/glibc-nscd-getpw_r-retry.patch | 17 + .../glibc/glibc-nscd-hst-noalias.patch | 19 + .../glibc/glibc-nscd-max-db-size.patch | 217 + src/patches/glibc/glibc-nscd-msync.patch | 19 + src/patches/glibc/glibc-nscd-paranoia.patch | 52 + src/patches/glibc/glibc-nscd-stat64.patch | 33 + src/patches/glibc/glibc-nscd-stats.patch | 41 + src/patches/glibc/glibc-nsswitch_conf.patch | 72 + src/patches/glibc/glibc-obstack_h-typo.patch | 18 + src/patches/glibc/glibc-ppc-assume.patch | 18 + src/patches/glibc/glibc-ppc-fegetround.patch | 19 + src/patches/glibc/glibc-ppc-libSegFault.patch | 49 + src/patches/glibc/glibc-ppc-strncmp.patch | 230 + .../glibc/glibc-prelink-dynamic-weak.patch | 17 + .../glibc/glibc-printf-string-len.patch | 22 + .../glibc/glibc-pthread_getattr_np.patch | 22 + src/patches/glibc/glibc-quota_h.patch | 16 + src/patches/glibc/glibc-readonly-area.patch | 44 + src/patches/glibc/glibc-regex_h-STDC.patch | 221 + src/patches/glibc/glibc-resolv-send_vc.patch | 17 + src/patches/glibc/glibc-rh168266.patch | 246 + src/patches/glibc/glibc-rh178934.patch | 337 ++ src/patches/glibc/glibc-rh184086.patch | 37 + src/patches/glibc/glibc-rh190259.patch | 29 + src/patches/glibc/glibc-rh191464.patch | 250 + src/patches/glibc/glibc-rh192072.patch | 508 ++ src/patches/glibc/glibc-rh193631.patch | 85 + src/patches/glibc/glibc-rh193873.patch | 158 + src/patches/glibc/glibc-rh194321.patch | 81 + src/patches/glibc/glibc-rh197790.patch | 77 + src/patches/glibc/glibc-rh197932.patch | 93 + src/patches/glibc/glibc-rh201748.patch | 18 + src/patches/glibc/glibc-rh201826.patch | 24 + src/patches/glibc/glibc-rh202991.patch | 207 + src/patches/glibc/glibc-rh203237.patch | 32 + src/patches/glibc/glibc-rh203728.patch | 65 + src/patches/glibc/glibc-rh203915.patch | 69 + src/patches/glibc/glibc-rh204122.patch | 98 + src/patches/glibc/glibc-rh205113.patch | 42 + src/patches/glibc/glibc-rh206483.patch | 45 + src/patches/glibc/glibc-rh206639.patch | 153 + src/patches/glibc/glibc-rh207928.patch | 89 + src/patches/glibc/glibc-rh208203.patch | 417 ++ .../glibc/glibc-rh210748-workaround.patch | 80 + src/patches/glibc/glibc-rh211116.patch | 157 + src/patches/glibc/glibc-rh215572.patch | 18 + src/patches/glibc/glibc-rh218782.patch | 50 + src/patches/glibc/glibc-rh218802.patch | 82 + src/patches/glibc/glibc-rh219145.patch | 38 + src/patches/glibc/glibc-rh220621.patch | 26 + src/patches/glibc/glibc-rh225315.patch | 1104 ++++ src/patches/glibc/glibc-rh227016.patch | 192 + src/patches/glibc/glibc-rh228103.patch | 17 + src/patches/glibc/glibc-rh228697.patch | 1934 ++++++ src/patches/glibc/glibc-rh230168.patch | 229 + src/patches/glibc/glibc-rh230197.patch | 22 + src/patches/glibc/glibc-rh233460.patch | 725 +++ src/patches/glibc/glibc-rh235229.patch | 225 + src/patches/glibc/glibc-rh237711.patch | 69 + src/patches/glibc/glibc-rh238431.patch | 41 + src/patches/glibc/glibc-rh247788.patch | 133 + src/patches/glibc/glibc-rh248281.patch | 132 + src/patches/glibc/glibc-rh254115.patch | 35 + src/patches/glibc/glibc-rh339821.patch | 17 + src/patches/glibc/glibc-rh346321.patch | 36 + src/patches/glibc/glibc-rh385601.patch | 1979 ++++++ src/patches/glibc/glibc-rh403231.patch | 186 + src/patches/glibc/glibc-rh405781.patch | 21 + src/patches/glibc/glibc-rh428859.patch | 10 + src/patches/glibc/glibc-rh434601.patch | 18 + src/patches/glibc/glibc-rh437571.patch | 469 ++ src/patches/glibc/glibc-rh455360.patch | 30 + src/patches/glibc/glibc-rh461481.patch | 96 + src/patches/glibc/glibc-rh464146.patch | 27 + src/patches/glibc/glibc-rh467309.patch | 140 + src/patches/glibc/glibc-rh470781.patch | 23 + src/patches/glibc/glibc-rtkaio-update.patch | 1735 ++++++ src/patches/glibc/glibc-s390-setjmp.patch | 16 + src/patches/glibc/glibc-scalb-namespace.patch | 25 + .../glibc/glibc-sched_getaffinity.patch | 27 + src/patches/glibc/glibc-sem_timedwait.patch | 164 + src/patches/glibc/glibc-sigwait-EINTR.patch | 34 + src/patches/glibc/glibc-sockatmark.patch | 16 + src/patches/glibc/glibc-stdio-put-error.patch | 85 + src/patches/glibc/glibc-strtod--0.patch | 148 + src/patches/glibc/glibc-strtod.patch | 301 + src/patches/glibc/glibc-strxfrm.patch | 149 + .../glibc/glibc-sysconf-intel-caches.patch | 76 + src/patches/glibc/glibc-tgmath-type.patch | 142 + src/patches/glibc/glibc-tls-model-ie.patch | 17 + .../glibc/glibc-tst-initializers1.patch | 55 + src/patches/glibc/glibc-tst-signal7.patch | 78 + src/patches/glibc/glibc-tzdata-update.patch | 596 ++ src/patches/glibc/glibc-wcstol-internal.patch | 43 + .../glibc/glibc-x86_64-gas-workaround.patch | 31 + .../glibc-x86_64-pthread_once-align.patch | 155 + src/patches/glibc/glibc-xtrace-options.patch | 17 + 268 files changed, 47911 insertions(+) create mode 100644 src/patches/glibc/glibc-2.3.6-fedora.patch create mode 100644 src/patches/glibc/glibc-DT_GNU_HASH.patch create mode 100644 src/patches/glibc/glibc-MALLOC_CHECK_.patch create mode 100644 src/patches/glibc/glibc-Wundef.patch create mode 100644 src/patches/glibc/glibc-aio-rh171968.patch create mode 100644 src/patches/glibc/glibc-argp-key.patch create mode 100644 src/patches/glibc/glibc-argp-vasprintf.patch create mode 100644 src/patches/glibc/glibc-argp_usage-NTH.patch create mode 100644 src/patches/glibc/glibc-asctime.patch create mode 100644 src/patches/glibc/glibc-bindresvport.patch create mode 100644 src/patches/glibc/glibc-byteswap.patch create mode 100644 src/patches/glibc/glibc-bz1051.patch create mode 100644 src/patches/glibc/glibc-bz1078.patch create mode 100644 src/patches/glibc/glibc-bz1201.patch create mode 100644 src/patches/glibc/glibc-bz1228.patch create mode 100644 src/patches/glibc/glibc-bz1230.patch create mode 100644 src/patches/glibc/glibc-bz1346.patch create mode 100644 src/patches/glibc/glibc-bz1548.patch create mode 100644 src/patches/glibc/glibc-bz1566.patch create mode 100644 src/patches/glibc/glibc-bz1579.patch create mode 100644 src/patches/glibc/glibc-bz1774.patch create mode 100644 src/patches/glibc/glibc-bz1913.patch create mode 100644 src/patches/glibc/glibc-bz1920.patch create mode 100644 src/patches/glibc/glibc-bz1925.patch create mode 100644 src/patches/glibc/glibc-bz1951.patch create mode 100644 src/patches/glibc/glibc-bz1952.patch create mode 100644 src/patches/glibc/glibc-bz1955.patch create mode 100644 src/patches/glibc/glibc-bz1962.patch create mode 100644 src/patches/glibc/glibc-bz1978.patch create mode 100644 src/patches/glibc/glibc-bz2013.patch create mode 100644 src/patches/glibc/glibc-bz2066.patch create mode 100644 src/patches/glibc/glibc-bz2072.patch create mode 100644 src/patches/glibc/glibc-bz2080.patch create mode 100644 src/patches/glibc/glibc-bz2126.patch create mode 100644 src/patches/glibc/glibc-bz2153.patch create mode 100644 src/patches/glibc/glibc-bz2173.patch create mode 100644 src/patches/glibc/glibc-bz2182.patch create mode 100644 src/patches/glibc/glibc-bz2226.patch create mode 100644 src/patches/glibc/glibc-bz2268.patch create mode 100644 src/patches/glibc/glibc-bz2415.patch create mode 100644 src/patches/glibc/glibc-bz2418.patch create mode 100644 src/patches/glibc/glibc-bz2420.patch create mode 100644 src/patches/glibc/glibc-bz2451.patch create mode 100644 src/patches/glibc/glibc-bz2498.patch create mode 100644 src/patches/glibc/glibc-bz2499.patch create mode 100644 src/patches/glibc/glibc-bz2501.patch create mode 100644 src/patches/glibc/glibc-bz2502.patch create mode 100644 src/patches/glibc/glibc-bz2509.patch create mode 100644 src/patches/glibc/glibc-bz2571.patch create mode 100644 src/patches/glibc/glibc-bz2592.patch create mode 100644 src/patches/glibc/glibc-bz2632.patch create mode 100644 src/patches/glibc/glibc-bz2644.patch create mode 100644 src/patches/glibc/glibc-bz2680.patch create mode 100644 src/patches/glibc/glibc-bz2684.patch create mode 100644 src/patches/glibc/glibc-bz2703.patch create mode 100644 src/patches/glibc/glibc-bz2766.patch create mode 100644 src/patches/glibc/glibc-bz2775.patch create mode 100644 src/patches/glibc/glibc-bz2792.patch create mode 100644 src/patches/glibc/glibc-bz2821.patch create mode 100644 src/patches/glibc/glibc-bz2841.patch create mode 100644 src/patches/glibc/glibc-bz2843.patch create mode 100644 src/patches/glibc/glibc-bz2892.patch create mode 100644 src/patches/glibc/glibc-bz2908.patch create mode 100644 src/patches/glibc/glibc-bz2998.patch create mode 100644 src/patches/glibc/glibc-bz3123.patch create mode 100644 src/patches/glibc/glibc-bz3124.patch create mode 100644 src/patches/glibc/glibc-bz3155.patch create mode 100644 src/patches/glibc/glibc-bz3253.patch create mode 100644 src/patches/glibc/glibc-bz3406.patch create mode 100644 src/patches/glibc/glibc-bz3451.patch create mode 100644 src/patches/glibc/glibc-bz3458.patch create mode 100644 src/patches/glibc/glibc-bz3842.patch create mode 100644 src/patches/glibc/glibc-bz3855.patch create mode 100644 src/patches/glibc/glibc-bz3902.patch create mode 100644 src/patches/glibc/glibc-bz394.patch create mode 100644 src/patches/glibc/glibc-bz3944.patch create mode 100644 src/patches/glibc/glibc-bz3957.patch create mode 100644 src/patches/glibc/glibc-bz4070.patch create mode 100644 src/patches/glibc/glibc-bz4074.patch create mode 100644 src/patches/glibc/glibc-bz4101.patch create mode 100644 src/patches/glibc/glibc-bz4130.patch create mode 100644 src/patches/glibc/glibc-bz4344.patch create mode 100644 src/patches/glibc/glibc-bz4349.patch create mode 100644 src/patches/glibc/glibc-bz4364.patch create mode 100644 src/patches/glibc/glibc-bz4405.patch create mode 100644 src/patches/glibc/glibc-bz4438.patch create mode 100644 src/patches/glibc/glibc-bz4439.patch create mode 100644 src/patches/glibc/glibc-bz4514.patch create mode 100644 src/patches/glibc/glibc-bz4586.patch create mode 100644 src/patches/glibc/glibc-bz4702.patch create mode 100644 src/patches/glibc/glibc-bz4745.patch create mode 100644 src/patches/glibc/glibc-bz4776.patch create mode 100644 src/patches/glibc/glibc-bz4813.patch create mode 100644 src/patches/glibc/glibc-bz4858.patch create mode 100644 src/patches/glibc/glibc-bz524.patch create mode 100644 src/patches/glibc/glibc-bz5854.patch create mode 100644 src/patches/glibc/glibc-bz644.patch create mode 100644 src/patches/glibc/glibc-bz6461.patch create mode 100644 src/patches/glibc/glibc-bz6719.patch create mode 100644 src/patches/glibc/glibc-bz714.patch create mode 100644 src/patches/glibc/glibc-bz968.patch create mode 100644 src/patches/glibc/glibc-coverity.patch create mode 100644 src/patches/glibc/glibc-coverity2.patch create mode 100644 src/patches/glibc/glibc-csqrt.patch create mode 100644 src/patches/glibc/glibc-ctermid.patch create mode 100644 src/patches/glibc/glibc-do_ypcall.patch create mode 100644 src/patches/glibc/glibc-doc-fixes.patch create mode 100644 src/patches/glibc/glibc-dst-req-static.patch create mode 100644 src/patches/glibc/glibc-dtv-is_static.patch create mode 100644 src/patches/glibc/glibc-elf64-filebuf-size.patch create mode 100644 src/patches/glibc/glibc-euidaccess.patch create mode 100644 src/patches/glibc/glibc-fgets-1.patch create mode 100644 src/patches/glibc/glibc-gai-leak.patch create mode 100644 src/patches/glibc/glibc-gconv-cache-memleak.patch create mode 100644 src/patches/glibc/glibc-getconf-a.patch create mode 100644 src/patches/glibc/glibc-getdelim-trunc.patch create mode 100644 src/patches/glibc/glibc-getent-gethostbyaddr.patch create mode 100644 src/patches/glibc/glibc-getent-leak.patch create mode 100644 src/patches/glibc/glibc-glob-getlogin_r.patch create mode 100644 src/patches/glibc/glibc-hwcap-mask.patch create mode 100644 src/patches/glibc/glibc-hypotf.patch create mode 100644 src/patches/glibc/glibc-i386-futex-timed-wait.patch create mode 100644 src/patches/glibc/glibc-i386-nosegneg.patch create mode 100644 src/patches/glibc/glibc-i386-timedrwlock.patch create mode 100644 src/patches/glibc/glibc-i686-memset.patch create mode 100644 src/patches/glibc/glibc-ia64-lib64.patch create mode 100644 src/patches/glibc/glibc-ia64-libm-error.patch create mode 100644 src/patches/glibc/glibc-ia64-mcount.patch create mode 100644 src/patches/glibc/glibc-ia64-post-upgrade-hack.patch create mode 100644 src/patches/glibc/glibc-ia64-shmatt_t.patch create mode 100644 src/patches/glibc/glibc-innetgr-leak.patch create mode 100644 src/patches/glibc/glibc-innetgr-thread-safety.patch create mode 100644 src/patches/glibc/glibc-ld-library-path-DST.patch create mode 100644 src/patches/glibc/glibc-ld_debug-conflicts.patch create mode 100644 src/patches/glibc/glibc-ldconfig-prelink.patch create mode 100644 src/patches/glibc/glibc-lddlibc4.patch create mode 100644 src/patches/glibc/glibc-linuxthreads-atomic_h.patch create mode 100644 src/patches/glibc/glibc-loadarchive-leak.patch create mode 100644 src/patches/glibc/glibc-localealias-leak.patch create mode 100644 src/patches/glibc/glibc-madvise-hidden.patch create mode 100644 src/patches/glibc/glibc-nan.patch create mode 100644 src/patches/glibc/glibc-nis+-batch.patch create mode 100644 src/patches/glibc/glibc-nis+-batch2.patch create mode 100644 src/patches/glibc/glibc-nis+-findserver.patch create mode 100644 src/patches/glibc/glibc-nis+-getenv.patch create mode 100644 src/patches/glibc/glibc-nis+-getnames.patch create mode 100644 src/patches/glibc/glibc-nis+-leaks.patch create mode 100644 src/patches/glibc/glibc-nis+-leaks2.patch create mode 100644 src/patches/glibc/glibc-nis+-parent.patch create mode 100644 src/patches/glibc/glibc-nis+.patch create mode 100644 src/patches/glibc/glibc-nis-getservbyname.patch create mode 100644 src/patches/glibc/glibc-nis-publickey.patch create mode 100644 src/patches/glibc/glibc-nis_leaf_of_r-0.patch create mode 100644 src/patches/glibc/glibc-nonnull.patch create mode 100644 src/patches/glibc/glibc-nptl-cancel-init.patch create mode 100644 src/patches/glibc/glibc-nptl-check.patch create mode 100644 src/patches/glibc/glibc-nptl-fork-cancel.patch create mode 100644 src/patches/glibc/glibc-nptl-fork-getpid.patch create mode 100644 src/patches/glibc/glibc-nptl-futex-wait.patch create mode 100644 src/patches/glibc/glibc-nptl-setxid-2.patch create mode 100644 src/patches/glibc/glibc-nptl-setxid.patch create mode 100644 src/patches/glibc/glibc-nscd-EINTR.patch create mode 100644 src/patches/glibc/glibc-nscd-LFS-logging.patch create mode 100644 src/patches/glibc/glibc-nscd-SIGHUP-disabled-cache.patch create mode 100644 src/patches/glibc/glibc-nscd-SIGHUP.patch create mode 100644 src/patches/glibc/glibc-nscd-addinitgroups.patch create mode 100644 src/patches/glibc/glibc-nscd-auto-propagate.patch create mode 100644 src/patches/glibc/glibc-nscd-db-checker.patch create mode 100644 src/patches/glibc/glibc-nscd-debug-verbose.patch create mode 100644 src/patches/glibc/glibc-nscd-fallocate.patch create mode 100644 src/patches/glibc/glibc-nscd-getpw_r-retry.patch create mode 100644 src/patches/glibc/glibc-nscd-hst-noalias.patch create mode 100644 src/patches/glibc/glibc-nscd-max-db-size.patch create mode 100644 src/patches/glibc/glibc-nscd-msync.patch create mode 100644 src/patches/glibc/glibc-nscd-paranoia.patch create mode 100644 src/patches/glibc/glibc-nscd-stat64.patch create mode 100644 src/patches/glibc/glibc-nscd-stats.patch create mode 100644 src/patches/glibc/glibc-nsswitch_conf.patch create mode 100644 src/patches/glibc/glibc-obstack_h-typo.patch create mode 100644 src/patches/glibc/glibc-ppc-assume.patch create mode 100644 src/patches/glibc/glibc-ppc-fegetround.patch create mode 100644 src/patches/glibc/glibc-ppc-libSegFault.patch create mode 100644 src/patches/glibc/glibc-ppc-strncmp.patch create mode 100644 src/patches/glibc/glibc-prelink-dynamic-weak.patch create mode 100644 src/patches/glibc/glibc-printf-string-len.patch create mode 100644 src/patches/glibc/glibc-pthread_getattr_np.patch create mode 100644 src/patches/glibc/glibc-quota_h.patch create mode 100644 src/patches/glibc/glibc-readonly-area.patch create mode 100644 src/patches/glibc/glibc-regex_h-STDC.patch create mode 100644 src/patches/glibc/glibc-resolv-send_vc.patch create mode 100644 src/patches/glibc/glibc-rh168266.patch create mode 100644 src/patches/glibc/glibc-rh178934.patch create mode 100644 src/patches/glibc/glibc-rh184086.patch create mode 100644 src/patches/glibc/glibc-rh190259.patch create mode 100644 src/patches/glibc/glibc-rh191464.patch create mode 100644 src/patches/glibc/glibc-rh192072.patch create mode 100644 src/patches/glibc/glibc-rh193631.patch create mode 100644 src/patches/glibc/glibc-rh193873.patch create mode 100644 src/patches/glibc/glibc-rh194321.patch create mode 100644 src/patches/glibc/glibc-rh197790.patch create mode 100644 src/patches/glibc/glibc-rh197932.patch create mode 100644 src/patches/glibc/glibc-rh201748.patch create mode 100644 src/patches/glibc/glibc-rh201826.patch create mode 100644 src/patches/glibc/glibc-rh202991.patch create mode 100644 src/patches/glibc/glibc-rh203237.patch create mode 100644 src/patches/glibc/glibc-rh203728.patch create mode 100644 src/patches/glibc/glibc-rh203915.patch create mode 100644 src/patches/glibc/glibc-rh204122.patch create mode 100644 src/patches/glibc/glibc-rh205113.patch create mode 100644 src/patches/glibc/glibc-rh206483.patch create mode 100644 src/patches/glibc/glibc-rh206639.patch create mode 100644 src/patches/glibc/glibc-rh207928.patch create mode 100644 src/patches/glibc/glibc-rh208203.patch create mode 100644 src/patches/glibc/glibc-rh210748-workaround.patch create mode 100644 src/patches/glibc/glibc-rh211116.patch create mode 100644 src/patches/glibc/glibc-rh215572.patch create mode 100644 src/patches/glibc/glibc-rh218782.patch create mode 100644 src/patches/glibc/glibc-rh218802.patch create mode 100644 src/patches/glibc/glibc-rh219145.patch create mode 100644 src/patches/glibc/glibc-rh220621.patch create mode 100644 src/patches/glibc/glibc-rh225315.patch create mode 100644 src/patches/glibc/glibc-rh227016.patch create mode 100644 src/patches/glibc/glibc-rh228103.patch create mode 100644 src/patches/glibc/glibc-rh228697.patch create mode 100644 src/patches/glibc/glibc-rh230168.patch create mode 100644 src/patches/glibc/glibc-rh230197.patch create mode 100644 src/patches/glibc/glibc-rh233460.patch create mode 100644 src/patches/glibc/glibc-rh235229.patch create mode 100644 src/patches/glibc/glibc-rh237711.patch create mode 100644 src/patches/glibc/glibc-rh238431.patch create mode 100644 src/patches/glibc/glibc-rh247788.patch create mode 100644 src/patches/glibc/glibc-rh248281.patch create mode 100644 src/patches/glibc/glibc-rh254115.patch create mode 100644 src/patches/glibc/glibc-rh339821.patch create mode 100644 src/patches/glibc/glibc-rh346321.patch create mode 100644 src/patches/glibc/glibc-rh385601.patch create mode 100644 src/patches/glibc/glibc-rh403231.patch create mode 100644 src/patches/glibc/glibc-rh405781.patch create mode 100644 src/patches/glibc/glibc-rh428859.patch create mode 100644 src/patches/glibc/glibc-rh434601.patch create mode 100644 src/patches/glibc/glibc-rh437571.patch create mode 100644 src/patches/glibc/glibc-rh455360.patch create mode 100644 src/patches/glibc/glibc-rh461481.patch create mode 100644 src/patches/glibc/glibc-rh464146.patch create mode 100644 src/patches/glibc/glibc-rh467309.patch create mode 100644 src/patches/glibc/glibc-rh470781.patch create mode 100644 src/patches/glibc/glibc-rtkaio-update.patch create mode 100644 src/patches/glibc/glibc-s390-setjmp.patch create mode 100644 src/patches/glibc/glibc-scalb-namespace.patch create mode 100644 src/patches/glibc/glibc-sched_getaffinity.patch create mode 100644 src/patches/glibc/glibc-sem_timedwait.patch create mode 100644 src/patches/glibc/glibc-sigwait-EINTR.patch create mode 100644 src/patches/glibc/glibc-sockatmark.patch create mode 100644 src/patches/glibc/glibc-stdio-put-error.patch create mode 100644 src/patches/glibc/glibc-strtod--0.patch create mode 100644 src/patches/glibc/glibc-strtod.patch create mode 100644 src/patches/glibc/glibc-strxfrm.patch create mode 100644 src/patches/glibc/glibc-sysconf-intel-caches.patch create mode 100644 src/patches/glibc/glibc-tgmath-type.patch create mode 100644 src/patches/glibc/glibc-tls-model-ie.patch create mode 100644 src/patches/glibc/glibc-tst-initializers1.patch create mode 100644 src/patches/glibc/glibc-tst-signal7.patch create mode 100644 src/patches/glibc/glibc-tzdata-update.patch create mode 100644 src/patches/glibc/glibc-wcstol-internal.patch create mode 100644 src/patches/glibc/glibc-x86_64-gas-workaround.patch create mode 100644 src/patches/glibc/glibc-x86_64-pthread_once-align.patch create mode 100644 src/patches/glibc/glibc-xtrace-options.patch diff --git a/lfs/glibc b/lfs/glibc index 82394a2e99..7aa58a96a9 100644 --- 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 index 0000000000..25be9a9b97 --- /dev/null +++ b/src/patches/glibc/glibc-2.3.6-fedora.patch @@ -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 + ++ * 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 ++ + * 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 ++ ++ * 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 + + * 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 ++ ++ * sysdeps/unix/sysv/linux/readonly-area.c (__readonly_area): If /proc ++ is not mounted, return 1. ++ + 2004-10-20 Roland McGrath + + * 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 ++ ++ * include/features.h (__USE_FORTIFY_LEVEL): Enable even with ++ Red Hat gcc4 4.0.0 and above. ++ + 2004-10-18 Jakub Jelinek + + * 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 ++ ++ * 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 + + * 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 + #include + +-#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 ++ ++ * 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 + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h +@@ -896,6 +902,34 @@ + + 2003-07-22 Jakub Jelinek + ++ * 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 ++ + * 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 + #endif ++#include + + #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 + #include + +-#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 + + /* 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 ++# 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 +--- 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 ++# 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 ++# 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 ++# 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 ++#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 ++# 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 ++# 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 ++# 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 ++# 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 "" + d_fmt "" + t_fmt "" +-am_pm "";"" +-t_fmt_ampm "" ++am_pm "";"" ++t_fmt_ampm "" ++date_fmt "/ ++/ ++" + 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 "" + d_fmt "" + t_fmt "" +-am_pm "";"" +-t_fmt_ampm "" ++am_pm "";"" ++t_fmt_ampm "" + date_fmt "/ + / + " +--- 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 " + "";/ + "";/ + "" +-am_pm "";"" + % Appropriate date and time representation (%c) + % "%a %d %b %Y %r %Z" + d_t_fmt "" +--- 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 ++ ++ * pthread_cond_destroy.c (__pthread_cond_destroy): If there are ++ waiters, awake all waiters on the associated mutex. ++ + 2004-09-02 Ulrich Drepper + + * 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 ++ ++ * 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 + + * 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 + #include + #include ++#ifdef __need_struct_pthread_size ++#define lll_lock_t int ++#else + #include + #include + #include ++#endif + #include "../nptl_db/thread_db.h" + #include + #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 ++ ++/* 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 + #include + #include ++#include + #include + #include + #include +@@ -42,6 +43,7 @@ + #include + #include + #include ++#include + + #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 ++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 , 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 ++ ++ ++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 +-#undef ret +- +-#include +- +-#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 ++#include ++ ++#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 +--- 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 +--- 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 ++#else ++#include ++#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 ++#else ++#include ++#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 index 0000000000..0983cbc835 --- /dev/null +++ b/src/patches/glibc/glibc-DT_GNU_HASH.patch @@ -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 index 0000000000..de1457a427 --- /dev/null +++ b/src/patches/glibc/glibc-MALLOC_CHECK_.patch @@ -0,0 +1,18 @@ +2006-04-24 Jakub Jelinek + + * 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 index 0000000000..7d3cce4d01 --- /dev/null +++ b/src/patches/glibc/glibc-Wundef.patch @@ -0,0 +1,38 @@ +2005-10-07 Roland McGrath + + [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 index 0000000000..66c2a0571e --- /dev/null +++ b/src/patches/glibc/glibc-aio-rh171968.patch @@ -0,0 +1,584 @@ +2006-09-05 Jakub Jelinek + Ulrich Drepper + + * sysdeps/pthread/aio_misc.h (AIO_MISC_NOTIFY): Don't decrement + counterp if it is already zero. + +2006-01-05 Ulrich Drepper + + * 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 + + * 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 + + * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 ++#include ++#include ++ ++#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 diff --git a/src/patches/glibc/glibc-argp-key.patch b/src/patches/glibc/glibc-argp-key.patch new file mode 100644 index 0000000000..74580b4cc7 --- /dev/null +++ b/src/patches/glibc/glibc-argp-key.patch @@ -0,0 +1,26 @@ +2006-04-21 Jakub Jelinek + + * 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 . + +--- 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 + #include + #include ++#include + + #define __need_error_t + #include +@@ -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 index 0000000000..5bfb378131 --- /dev/null +++ b/src/patches/glibc/glibc-argp-vasprintf.patch @@ -0,0 +1,39 @@ +2005-08-08 Ulrich Drepper + + * argp/argp-help.c: Use _IO_vasprintf instead of vasprintf. + +2005-08-08 Roland McGrath + + * 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 + #include + #include +-#ifdef USE_IN_LIBIO ++#ifdef _LIBC ++# include <../libio/libioP.h> + # include + #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 index 0000000000..74979cf380 --- /dev/null +++ b/src/patches/glibc/glibc-argp_usage-NTH.patch @@ -0,0 +1,16 @@ +2005-10-13 Ulrich Drepper + + [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 index 0000000000..958e0a3a35 --- /dev/null +++ b/src/patches/glibc/glibc-asctime.patch @@ -0,0 +1,191 @@ +2005-10-14 Ulrich Drepper + + * 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 ++#include + #include + #include + +@@ -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 ++#include ++#include ++#include ++ ++ ++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 ++#include ++#include ++#include ++ ++ ++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 index 0000000000..f735f64a97 --- /dev/null +++ b/src/patches/glibc/glibc-bindresvport.patch @@ -0,0 +1,37 @@ +2005-11-21 Jakub Jelinek + + * 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 index 0000000000..9cbc287173 --- /dev/null +++ b/src/patches/glibc/glibc-byteswap.patch @@ -0,0 +1,44 @@ +2007-02-12 Jakub Jelinek + + * 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 + + * 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 + + [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 index 0000000000..b4f65fc105 --- /dev/null +++ b/src/patches/glibc/glibc-bz1051.patch @@ -0,0 +1,155 @@ +2005-09-22 Roland McGrath + + * Makefile ($(objpfx)c++-types-check.out): Use $<, not $^, in command. + Reported by Alexandre Oliva . + +2005-09-17 Ulrich Drepper + + [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 . + * 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 index 0000000000..b4d7e16ed3 --- /dev/null +++ b/src/patches/glibc/glibc-bz1078.patch @@ -0,0 +1,151 @@ +2005-09-27 Ulrich Drepper + + [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 ++#include ++#include ++ ++#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 index 0000000000..1cc6cc11f1 --- /dev/null +++ b/src/patches/glibc/glibc-bz1201.patch @@ -0,0 +1,17 @@ +2006-05-02 Ulrich Drepper + + [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 index 0000000000..ff40aae3c3 --- /dev/null +++ b/src/patches/glibc/glibc-bz1228.patch @@ -0,0 +1,40 @@ +2005-09-13 Jakub Jelinek + + [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 ++#endif + + /* The 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 index 0000000000..f95395f258 --- /dev/null +++ b/src/patches/glibc/glibc-bz1230.patch @@ -0,0 +1,114 @@ +2005-09-27 Ulrich Drepper + + [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 ++#include ++#include ++#include ++ ++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 index 0000000000..84077ca877 --- /dev/null +++ b/src/patches/glibc/glibc-bz1346.patch @@ -0,0 +1,55 @@ +2005-09-20 Roland McGrath + + [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 index 0000000000..30e7044b4e --- /dev/null +++ b/src/patches/glibc/glibc-bz1548.patch @@ -0,0 +1,18 @@ +2005-11-03 Roland McGrath + + [BZ #1548] + * sunrpc/svc.c (svc_getreqset): Use ffsl instead of ffs on fd_mask, + make sure constant is long. + From Jay Lan . + +--- 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 index 0000000000..84ae34e253 --- /dev/null +++ b/src/patches/glibc/glibc-bz1566.patch @@ -0,0 +1,19 @@ +2005-12-23 Ulrich Drepper + + [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 +--- 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 index 0000000000..40ae164e1f --- /dev/null +++ b/src/patches/glibc/glibc-bz1579.patch @@ -0,0 +1,17 @@ +2005-10-31 Ulrich Drepper + + [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 index 0000000000..48514c14ff --- /dev/null +++ b/src/patches/glibc/glibc-bz1774.patch @@ -0,0 +1,43 @@ +2005-11-03 Ulrich Drepper + + [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 index 0000000000..a37223b0b8 --- /dev/null +++ b/src/patches/glibc/glibc-bz1913.patch @@ -0,0 +1,26 @@ +2005-12-22 Ulrich Drepper + + [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 index 0000000000..090345fd67 --- /dev/null +++ b/src/patches/glibc/glibc-bz1920.patch @@ -0,0 +1,52 @@ +2005-11-24 Ulrich Drepper + + * 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 + + [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 index 0000000000..d6d8b722a4 --- /dev/null +++ b/src/patches/glibc/glibc-bz1925.patch @@ -0,0 +1,16 @@ +2005-11-25 Ulrich Drepper + + [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 index 0000000000..f60406a5ee --- /dev/null +++ b/src/patches/glibc/glibc-bz1951.patch @@ -0,0 +1,253 @@ +2006-04-23 Ulrich Drepper + + [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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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\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 index 0000000000..f8932f60ee --- /dev/null +++ b/src/patches/glibc/glibc-bz1952.patch @@ -0,0 +1,65 @@ +2005-12-20 Jakub Jelinek + + * sysdeps/unix/sysv/linux/time.c: If __NR_time is not defined, + use sysdeps/unix/time.c implementation. + +2005-12-19 Ulrich Drepper + + [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 ++#include ++ ++#include ++ ++#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 ++ ++#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 index 0000000000..70b09d5d61 --- /dev/null +++ b/src/patches/glibc/glibc-bz1955.patch @@ -0,0 +1,17 @@ +2005-12-19 Ulrich Drepper + + [BZ #1955] + * timezone/zic.c (tofile;): Fix typo in symlink creation. + Patch by Phil Estes . + +--- 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 index 0000000000..16abba0245 --- /dev/null +++ b/src/patches/glibc/glibc-bz1962.patch @@ -0,0 +1,67 @@ +2005-12-21 Ulrich Drepper + + [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 index 0000000000..36ad5469fb --- /dev/null +++ b/src/patches/glibc/glibc-bz1978.patch @@ -0,0 +1,55 @@ +2005-12-16 Thorsten Kukuk + + [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 index 0000000000..0d892bf0f7 --- /dev/null +++ b/src/patches/glibc/glibc-bz2013.patch @@ -0,0 +1,81 @@ +2006-01-05 H.J. Lu + + [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 index 0000000000..0e267de8a0 --- /dev/null +++ b/src/patches/glibc/glibc-bz2066.patch @@ -0,0 +1,20 @@ +2005-12-21 Roland McGrath + + [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 index 0000000000..3522f65971 --- /dev/null +++ b/src/patches/glibc/glibc-bz2072.patch @@ -0,0 +1,84 @@ +2006-04-25 Ulrich Drepper + + [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 index 0000000000..98ead608fd --- /dev/null +++ b/src/patches/glibc/glibc-bz2080.patch @@ -0,0 +1,19 @@ +2005-12-30 Ulrich Drepper + + [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 index 0000000000..aee48791ee --- /dev/null +++ b/src/patches/glibc/glibc-bz2126.patch @@ -0,0 +1,118 @@ +2006-01-09 Ulrich Drepper + + [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 ++#include ++ ++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 index 0000000000..1961167b56 --- /dev/null +++ b/src/patches/glibc/glibc-bz2153.patch @@ -0,0 +1,281 @@ +2006-01-15 Andreas Jaeger + + [BZ #2153] + * sysdeps/generic/s_cacosh.c (__cacosh): Do not return a negative + value. Patch by Wes Loewer . + * 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 index 0000000000..43bcee9cd1 --- /dev/null +++ b/src/patches/glibc/glibc-bz2173.patch @@ -0,0 +1,150 @@ +2006-01-18 Ulrich Drepper + + [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 ++#include ++#include ++#include ++#include ++ ++ ++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 index 0000000000..ed134243f2 --- /dev/null +++ b/src/patches/glibc/glibc-bz2182.patch @@ -0,0 +1,46 @@ +2006-08-03 Ulrich Drepper + + [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 index 0000000000..189bdf2e4d --- /dev/null +++ b/src/patches/glibc/glibc-bz2226.patch @@ -0,0 +1,17 @@ +2006-02-12 Ulrich Drepper + + [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 index 0000000000..d0df514bf8 --- /dev/null +++ b/src/patches/glibc/glibc-bz2268.patch @@ -0,0 +1,25 @@ +2006-02-03 Roland McGrath + + [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 + #include + #include ++#include + + #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 index 0000000000..6d5e087e95 --- /dev/null +++ b/src/patches/glibc/glibc-bz2415.patch @@ -0,0 +1,22 @@ +2006-04-01 Ulrich Drepper + + [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 index 0000000000..d1a37468c7 --- /dev/null +++ b/src/patches/glibc/glibc-bz2418.patch @@ -0,0 +1,25 @@ +2006-04-02 Ulrich Drepper + + [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 + #include + #include ++#include + + #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 index 0000000000..3a40753807 --- /dev/null +++ b/src/patches/glibc/glibc-bz2420.patch @@ -0,0 +1,131 @@ +2006-04-25 Ulrich Drepper + + [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 ++#include ++#include ++#include ++ ++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 index 0000000000..9298e86664 --- /dev/null +++ b/src/patches/glibc/glibc-bz2451.patch @@ -0,0 +1,147 @@ +2006-03-17 Roland McGrath + + * elf/tst-leaks1.c: Include . + +2006-03-13 Jakub Jelinek + + [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 ++#include ++#include ++#include ++ ++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 index 0000000000..46f547174c --- /dev/null +++ b/src/patches/glibc/glibc-bz2498.patch @@ -0,0 +1,44 @@ +2006-04-01 Ulrich Drepper + + [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 index 0000000000..73b6cad333 --- /dev/null +++ b/src/patches/glibc/glibc-bz2499.patch @@ -0,0 +1,97 @@ +2006-05-06 Ulrich Drepper + + [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 index 0000000000..e7ce6922d2 --- /dev/null +++ b/src/patches/glibc/glibc-bz2501.patch @@ -0,0 +1,76 @@ +2006-04-02 Ulrich Drepper + + [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 index 0000000000..b84711d93e --- /dev/null +++ b/src/patches/glibc/glibc-bz2502.patch @@ -0,0 +1,17 @@ +2006-05-01 Ulrich Drepper + + [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 index 0000000000..d8051d4fe3 --- /dev/null +++ b/src/patches/glibc/glibc-bz2509.patch @@ -0,0 +1,89 @@ +2006-05-05 Jakub Jelinek + + [BZ #2509] + * stdio-common/tst-printf.sh: Adjust for tst-printf.c change even + on 32-bit arches. + +2006-05-02 Ulrich Drepper + + [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 index 0000000000..782c498d77 --- /dev/null +++ b/src/patches/glibc/glibc-bz2571.patch @@ -0,0 +1,53 @@ +2006-04-25 Ulrich Drepper + + [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 index 0000000000..aafad647a3 --- /dev/null +++ b/src/patches/glibc/glibc-bz2592.patch @@ -0,0 +1,447 @@ +2006-09-24 Jakub Jelinek + + * sysdeps/ieee754/ldbl-128/s_lrintl.c (__lrintl): Fix 2 typos. + +2006-09-20 Andreas Jaeger + + * math/libm-test.inc (lrint_test_upward): Fix typo. + +2006-06-17 Joseph S. Myers + + [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 index 0000000000..a53ccce0c6 --- /dev/null +++ b/src/patches/glibc/glibc-bz2632.patch @@ -0,0 +1,17 @@ +2006-05-02 Ulrich Drepper + + [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 index 0000000000..e4e4a66a8f --- /dev/null +++ b/src/patches/glibc/glibc-bz2644.patch @@ -0,0 +1,35 @@ +2006-05-09 Ulrich Drepper + + [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 + + [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 index 0000000000..10ada67549 --- /dev/null +++ b/src/patches/glibc/glibc-bz2680.patch @@ -0,0 +1,17 @@ +2006-05-21 Joseph S. Myers + + [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 index 0000000000..4f4e345d25 --- /dev/null +++ b/src/patches/glibc/glibc-bz2684.patch @@ -0,0 +1,39 @@ +2006-08-27 Ulrich Drepper + + [BZ #2684] + * malloc/malloc.c (public_rEALLOc): Try harder by using other + arenas if allocation failed. + Patch mostly by Jan Edler . + +--- 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 index 0000000000..708bc39346 --- /dev/null +++ b/src/patches/glibc/glibc-bz2703.patch @@ -0,0 +1,113 @@ +2006-06-04 Ulrich Drepper + + * string/Makefile (tests): Add bug-envz1. + * string/bug-enz1.c: New file. + +2006-06-02 Ryan S. Arnold + + [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 ++#include ++#include ++#include ++ ++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 index 0000000000..d13c5b1968 --- /dev/null +++ b/src/patches/glibc/glibc-bz2766.patch @@ -0,0 +1,111 @@ +2006-06-14 Jakub Jelinek + + [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 ++#include ++#include ++ ++#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 index 0000000000..e0155074b1 --- /dev/null +++ b/src/patches/glibc/glibc-bz2775.patch @@ -0,0 +1,32 @@ +2006-09-07 Jakub Jelinek + + [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 index 0000000000..6e8962fb69 --- /dev/null +++ b/src/patches/glibc/glibc-bz2792.patch @@ -0,0 +1,32 @@ +2006-06-17 Ulrich Drepper + + [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 index 0000000000..761893b0b3 --- /dev/null +++ b/src/patches/glibc/glibc-bz2821.patch @@ -0,0 +1,55 @@ +2006-09-09 Ulrich Drepper + + [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 ++#include ++ ++ ++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 index 0000000000..88ad720621 --- /dev/null +++ b/src/patches/glibc/glibc-bz2841.patch @@ -0,0 +1,20 @@ +2006-06-23 Paul Eggert + + [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 index 0000000000..f509feb5d5 --- /dev/null +++ b/src/patches/glibc/glibc-bz2843.patch @@ -0,0 +1,359 @@ +2006-08-12 Ulrich Drepper + + [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 + #include + #include ++#include ++#include ++#include ++ ++ ++#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 index 0000000000..a2ecd0b6a2 --- /dev/null +++ b/src/patches/glibc/glibc-bz2892.patch @@ -0,0 +1,19 @@ +2006-08-03 Ulrich Drepper + + [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 index 0000000000..29c74f1a82 --- /dev/null +++ b/src/patches/glibc/glibc-bz2908.patch @@ -0,0 +1,93 @@ +2006-08-08 Jakub Jelinek + + * 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 + + [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 ++#include ++ ++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 index 0000000000..ecf8a6ebaa --- /dev/null +++ b/src/patches/glibc/glibc-bz2998.patch @@ -0,0 +1,19 @@ +2006-08-03 Eric Blake + + [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 index 0000000000..d260929be4 --- /dev/null +++ b/src/patches/glibc/glibc-bz3123.patch @@ -0,0 +1,297 @@ +2006-09-12 Ulrich Drepper + + * tst-cond22.c (tf): Slight changes to the pthread_cond_wait use + to guarantee the thread is always canceled. + +2006-09-08 Jakub Jelinek + + * 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 + + [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 ++#include ++#include ++ ++ ++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 index 0000000000..b6895bd1bf --- /dev/null +++ b/src/patches/glibc/glibc-bz3124.patch @@ -0,0 +1,241 @@ +2006-09-05 Ulrich Drepper + + [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 ++#include ++#include ++#include ++ ++ ++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 index 0000000000..4fd90898d6 --- /dev/null +++ b/src/patches/glibc/glibc-bz3155.patch @@ -0,0 +1,27 @@ +2006-09-07 Jakub Jelinek + + [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 + + /* 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 index 0000000000..e470a27071 --- /dev/null +++ b/src/patches/glibc/glibc-bz3253.patch @@ -0,0 +1,271 @@ +2006-09-30 Ulrich Drepper + + * sysdeps/generic/glob.c (glob_in_dir): Add some comments and asserts to + explain why there are no leaks. + +2006-09-25 Jakub Jelinek + + [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 index 0000000000..3a9b4331c7 --- /dev/null +++ b/src/patches/glibc/glibc-bz3406.patch @@ -0,0 +1,27 @@ +2008-02-11 Joseph Myers + + [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 index 0000000000..ab8a67209e --- /dev/null +++ b/src/patches/glibc/glibc-bz3451.patch @@ -0,0 +1,62 @@ +2006-11-10 Ulrich Drepper + + [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 index 0000000000..fe10bfacc8 --- /dev/null +++ b/src/patches/glibc/glibc-bz3458.patch @@ -0,0 +1,57 @@ +2007-02-21 Ulrich Drepper + + [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 ++#include ++ ++ ++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 index 0000000000..19dcce74a1 --- /dev/null +++ b/src/patches/glibc/glibc-bz3842.patch @@ -0,0 +1,30 @@ +2007-02-17 Ulrich Drepper + + [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 index 0000000000..f0c541a1a3 --- /dev/null +++ b/src/patches/glibc/glibc-bz3855.patch @@ -0,0 +1,204 @@ +2007-01-11 Jakub Jelinek + + * 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 + + * 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 + #include + ++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 ++#include ++#include ++#include ++ ++#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 index 0000000000..f6ac97df80 --- /dev/null +++ b/src/patches/glibc/glibc-bz3902.patch @@ -0,0 +1,71 @@ +2007-01-22 Ulrich Drepper + + [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 ++#include ++ ++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 index 0000000000..3296ea2d0f --- /dev/null +++ b/src/patches/glibc/glibc-bz394.patch @@ -0,0 +1,40 @@ +2005-09-23 Ulrich Drepper + + [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 index 0000000000..5d6588b922 --- /dev/null +++ b/src/patches/glibc/glibc-bz3944.patch @@ -0,0 +1,109 @@ +2007-02-08 Jakub Jelinek + + [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 ++#include ++#include ++#include ++ ++ ++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 index 0000000000..8e16de1404 --- /dev/null +++ b/src/patches/glibc/glibc-bz3957.patch @@ -0,0 +1,189 @@ +2007-02-05 Jakub Jelinek + + [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 , 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 ++#include ++#include ++ ++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 , 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 ++#include ++#include ++ ++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 index 0000000000..adc9f791e2 --- /dev/null +++ b/src/patches/glibc/glibc-bz4070.patch @@ -0,0 +1,207 @@ +2007-04-13 Jakub Jelinek + + * 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 + + [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 + + * 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 index 0000000000..6909df6020 --- /dev/null +++ b/src/patches/glibc/glibc-bz4074.patch @@ -0,0 +1,29 @@ +2007-02-21 Ulrich Drepper + + * 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 index 0000000000..5818d683d1 --- /dev/null +++ b/src/patches/glibc/glibc-bz4101.patch @@ -0,0 +1,148 @@ +2007-03-15 Jakub Jelinek + + [BZ #4101] + * argp/argp-help.c (hol_cluster_cmp): Fix comparisons used to find + ancestors with the same depths. + Patch by Niels Moeller . + (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 , 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 ++ ++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 index 0000000000..b45112e498 --- /dev/null +++ b/src/patches/glibc/glibc-bz4130.patch @@ -0,0 +1,32 @@ +2007-03-15 Jakub Jelinek + + [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 index 0000000000..615d017e85 --- /dev/null +++ b/src/patches/glibc/glibc-bz4344.patch @@ -0,0 +1,34 @@ +2007-04-13 Jakub Jelinek + + [BZ #4344] + * elf/ldconfig.c (search_dir): Fix 2 off-by-2 errors. + Reported by David Anderson . + +--- 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 index 0000000000..95f55f7060 --- /dev/null +++ b/src/patches/glibc/glibc-bz4349.patch @@ -0,0 +1,278 @@ +2007-05-21 Jakub Jelinek + + * 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 + Jakub Jelinek + + [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 . + +--- 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(iav[2*i+2]))==i && +- largebin_index(chunksize(ms->av[2*i+3]))==i)) { ++ if(0 && ++ (iav[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 index 0000000000..836a09ba1c --- /dev/null +++ b/src/patches/glibc/glibc-bz4364.patch @@ -0,0 +1,18 @@ +2007-04-16 Ulrich Drepper + + [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 index 0000000000..58c06527a5 --- /dev/null +++ b/src/patches/glibc/glibc-bz4405.patch @@ -0,0 +1,17 @@ +2007-04-23 Jakub Jelinek + + [BZ #4405] + * iconvdata/gconv-modules (E13B): Add a missing slash to the alias + name. Patch by Aurelien Jarno . + +--- 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 index 0000000000..d61f8e0cb7 --- /dev/null +++ b/src/patches/glibc/glibc-bz4438.patch @@ -0,0 +1,81 @@ +2007-05-04 Ulrich Drepper + + * stdio-common/vfprintf.c (process_string_arg): Adjust call to + __mbsnrtowcs after last change. + +2007-05-02 Jakub Jelinek + + * stdio-common/vfprintf.c (process_string_arg): Use a VLA rather than + fixed length array for ignore. + +2007-04-30 Ulrich Drepper + + [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 index 0000000000..7074e92d7b --- /dev/null +++ b/src/patches/glibc/glibc-bz4439.patch @@ -0,0 +1,144 @@ +2007-04-30 Jakub Jelinek + + [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 ++#include ++#include ++#include ++#include ++ ++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 index 0000000000..fa37c9137c --- /dev/null +++ b/src/patches/glibc/glibc-bz4514.patch @@ -0,0 +1,79 @@ +2007-05-21 Jakub Jelinek + + [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 index 0000000000..4ec883cb6e --- /dev/null +++ b/src/patches/glibc/glibc-bz4586.patch @@ -0,0 +1,50 @@ +2007-06-06 Jakub Jelinek + + [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 + #include + #include + +@@ -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 index 0000000000..1c10cdffcd --- /dev/null +++ b/src/patches/glibc/glibc-bz4702.patch @@ -0,0 +1,32 @@ +2007-07-03 Jakub Jelinek + + [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 ++#include + #include + #include + #include +@@ -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 index 0000000000..9f674b4372 --- /dev/null +++ b/src/patches/glibc/glibc-bz4745.patch @@ -0,0 +1,169 @@ +2007-07-07 Ulrich Drepper + + [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 ++#include ++#include ++ ++#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 ++#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 ++#include ++#include ++ ++#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 ++#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 index 0000000000..10472e6543 --- /dev/null +++ b/src/patches/glibc/glibc-bz4776.patch @@ -0,0 +1,86 @@ +2007-07-11 Jakub Jelinek + + [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 index 0000000000..798ed7ffb9 --- /dev/null +++ b/src/patches/glibc/glibc-bz4813.patch @@ -0,0 +1,18 @@ +2007-07-20 Jakub Jelinek + + [BZ #4813] + * login/forkpty.c (forkpty): Close master and slave fds on + fork failure. Patch by + Mikulas Patocka . + +--- 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 index 0000000000..2cf2403aee --- /dev/null +++ b/src/patches/glibc/glibc-bz4858.patch @@ -0,0 +1,48 @@ +2007-07-31 Jakub Jelinek + + * stdio-common/tfformat.c (sprint_doubles): Add 12 new tests. + +2007-07-28 Ulrich Drepper + + [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 index 0000000000..311f2f67c0 --- /dev/null +++ b/src/patches/glibc/glibc-bz524.patch @@ -0,0 +1,18 @@ +2005-09-26 Ulrich Drepper + + [BZ #524] + * sysdeps/posix/getaddrinfo.c (match_prefix): Fix matching loop of + number of bits is multiple of 8. + Patch by Fredrik Tolf . + +--- 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 index 0000000000..d755cb5422 --- /dev/null +++ b/src/patches/glibc/glibc-bz5854.patch @@ -0,0 +1,18 @@ +2008-03-03 Ulrich Drepper + + [BZ #5854] + * nis/ypclnt.c (yp_order): Fix handling of return value of + do_ypcall_tr call. + Patch by Jeff Moyer . + +--- 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 index 0000000000..3f3fa3e0ae --- /dev/null +++ b/src/patches/glibc/glibc-bz644.patch @@ -0,0 +1,171 @@ +2005-09-26 Ulrich Drepper + + [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 ++#include ++ ++/* 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 index 0000000000..c5117c82fe --- /dev/null +++ b/src/patches/glibc/glibc-bz6461.patch @@ -0,0 +1,39 @@ +2008-05-14 Ulrich Drepper + + [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 +@@ -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 diff --git a/src/patches/glibc/glibc-bz6719.patch b/src/patches/glibc/glibc-bz6719.patch new file mode 100644 index 0000000000..adea77f2b6 --- /dev/null +++ b/src/patches/glibc/glibc-bz6719.patch @@ -0,0 +1,69 @@ +2008-07-08 Ulrich Drepper + + * 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 . + +--- 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 ++ ++static int ++do_test (void) ++{ ++ if (setvbuf (stderr, NULL, _IOFBF, BUFSIZ) != 0) ++ { ++ puts ("Set full buffer error."); ++ return 1; ++ } ++ ++ fprintf (stderr, "Output #1 .\n"); ++ printf ("Output #2 .\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 . ++Output #1 . diff --git a/src/patches/glibc/glibc-bz714.patch b/src/patches/glibc/glibc-bz714.patch new file mode 100644 index 0000000000..e107135178 --- /dev/null +++ b/src/patches/glibc/glibc-bz714.patch @@ -0,0 +1,107 @@ +2005-10-15 Ulrich Drepper + + * 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 + + [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 ++#include ++#include ++#include ++ ++ ++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 index 0000000000..69b37ae27f --- /dev/null +++ b/src/patches/glibc/glibc-bz968.patch @@ -0,0 +1,29 @@ +2005-10-15 Ulrich Drepper + + [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 index 0000000000..17d4251222 --- /dev/null +++ b/src/patches/glibc/glibc-coverity.patch @@ -0,0 +1,1608 @@ +2006-05-01 Ulrich Drepper + + * 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 + + * 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 + + * sysdeps/generic/unwind-dw2-fde.c (end_fde_sort): Remove + unnecessary test for accu->linear == NULL [Coverity CID 79]. + +2006-04-07 Ulrich Drepper + + * 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 + + * sysdeps/generic/unwind-dw2.c (execute_cfa_program): Fix typo in + the last change. + +2006-04-07 Ulrich Drepper + + * 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 + + * 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 + + * 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 + #include + #include ++#include + #include + #include + #include +@@ -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 index 0000000000..b36bdf8556 --- /dev/null +++ b/src/patches/glibc/glibc-coverity2.patch @@ -0,0 +1,854 @@ +2006-05-10 Ulrich Drepper + + * 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 + + * 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 + #include + #include + #include +@@ -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 "=" ? */ ++ 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 ++ ++ ++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 index 0000000000..ed5eaad3c7 --- /dev/null +++ b/src/patches/glibc/glibc-csqrt.patch @@ -0,0 +1,69 @@ +2005-10-13 Ulrich Drepper + + [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 index 0000000000..11fe945618 --- /dev/null +++ b/src/patches/glibc/glibc-ctermid.patch @@ -0,0 +1,15 @@ +2006-01-03 Jakub Jelinek + + * 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 . */ + #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 index 0000000000..59145e6314 --- /dev/null +++ b/src/patches/glibc/glibc-do_ypcall.patch @@ -0,0 +1,16 @@ +2005-11-26 Ulrich Drepper + + * 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 index 0000000000..50dcd05357 --- /dev/null +++ b/src/patches/glibc/glibc-doc-fixes.patch @@ -0,0 +1,103 @@ +2006-02-03 Jakub Jelinek + + * manual/filesys.texi (futimes): Fix prototype. + +2004-08-09 Paul Eggert + + [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 + . + +2006-02-03 Ulrich Drepper + + * manual/stdio.texi (Formatted Output Functions): Fix make_message + example. Patch by NIIBE Yutaka . + +2005-12-31 Andreas Jaeger + + [BZ #1395] + * manual/filesys.texi (Symbolic Links): Fix description of + canonicalize_file_name based on patch by Oskar Liljeblad + . + +2005-12-15 Roland McGrath + + [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 index 0000000000..2161a0f2eb --- /dev/null +++ b/src/patches/glibc/glibc-dst-req-static.patch @@ -0,0 +1,58 @@ +2007-03-16 Jakub Jelinek + + * 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 index 0000000000..d1b5c621f2 --- /dev/null +++ b/src/patches/glibc/glibc-dtv-is_static.patch @@ -0,0 +1,642 @@ +2006-02-03 Roland McGrath + + * 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 + + * 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 + + * 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 + + #ifndef __ASSEMBLER__ ++# include + # include + # include + +@@ -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 + #ifndef __ASSEMBLER__ ++# include + # include + # include + # include +@@ -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 + + #ifndef __ASSEMBLER__ ++# include + # include + # include + +@@ -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 + #ifndef __ASSEMBLER__ ++# include + # include + # include + # include +@@ -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 + + #ifndef __ASSEMBLER__ ++# include + # include + # include + +@@ -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 + #ifndef __ASSEMBLER__ ++# include + # include + # include + # include +@@ -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 + #ifndef __ASSEMBLER__ ++# include + # include + # include + # include +@@ -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 /* For ARCH_SET_FS. */ + #ifndef __ASSEMBLER__ ++# include + # include + # include + # include +@@ -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 + # include ++# include + + /* 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 + # include ++# include + + /* 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 + # include ++# include + + /* 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 + # include ++# include + + /* 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 + # include ++# include + + /* 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 + + #ifndef __ASSEMBLER__ ++# include + # include + # include + +@@ -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 + # include + # include + # include +@@ -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 + # include ++# include + + /* 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 index 0000000000..f2c0bde2b6 --- /dev/null +++ b/src/patches/glibc/glibc-elf64-filebuf-size.patch @@ -0,0 +1,35 @@ +2005-07-30 Ulrich Drepper + + * 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 index 0000000000..b6dd2e2d0d --- /dev/null +++ b/src/patches/glibc/glibc-euidaccess.patch @@ -0,0 +1,70 @@ +2005-11-27 Ulrich Drepper + + * 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 index 0000000000..f4b87f0d3d --- /dev/null +++ b/src/patches/glibc/glibc-fgets-1.patch @@ -0,0 +1,112 @@ +2005-09-26 Ulrich Drepper + + [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 ++ ++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 index 0000000000..5b28835ec4 --- /dev/null +++ b/src/patches/glibc/glibc-gai-leak.patch @@ -0,0 +1,36 @@ +2006-03-29 Ulrich Drepper + + * 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 index 0000000000..0429645560 --- /dev/null +++ b/src/patches/glibc/glibc-gconv-cache-memleak.patch @@ -0,0 +1,16 @@ +2006-01-10 Ulrich Drepper + + * 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 index 0000000000..9f083acef5 --- /dev/null +++ b/src/patches/glibc/glibc-getconf-a.patch @@ -0,0 +1,81 @@ +2005-01-11 Thorsten Kukuk + + [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 . + +--- 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 index 0000000000..ce5c1f1b4d --- /dev/null +++ b/src/patches/glibc/glibc-getdelim-trunc.patch @@ -0,0 +1,30 @@ +2005-10-13 Ulrich Drepper + + [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 index 0000000000..26cbf36493 --- /dev/null +++ b/src/patches/glibc/glibc-getent-gethostbyaddr.patch @@ -0,0 +1,19 @@ +2005-10-08 Jakub Jelinek + + * 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 index 0000000000..b03db4ced0 --- /dev/null +++ b/src/patches/glibc/glibc-getent-leak.patch @@ -0,0 +1,15 @@ +2005-09-09 Ulrich Drepper + + * 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 index 0000000000..634eb772fb --- /dev/null +++ b/src/patches/glibc/glibc-glob-getlogin_r.patch @@ -0,0 +1,17 @@ +2005-07-11 Derek R. Price + + [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 index 0000000000..b04897b567 --- /dev/null +++ b/src/patches/glibc/glibc-hwcap-mask.patch @@ -0,0 +1,89 @@ +2007-07-01 Jakub Jelinek + + * 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 index 0000000000..e66bfd30dd --- /dev/null +++ b/src/patches/glibc/glibc-hypotf.patch @@ -0,0 +1,51 @@ +2005-08-31 Bob Wilson + + * 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 + + * sysdeps/ieee754/flt-32/e_hypotf.c [!__STDC__]: Fix function name. + +2005-08-01 Bob Wilson + Richard Sandiford + + * 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 index 0000000000..8ece3d2af0 --- /dev/null +++ b/src/patches/glibc/glibc-i386-futex-timed-wait.patch @@ -0,0 +1,92 @@ +2006-02-08 Jakub Jelinek + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_futex_timedwait): + Add "memory" clobber. + +2006-01-05 Ulrich Drepper + + * 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 index 0000000000..d4157e7907 --- /dev/null +++ b/src/patches/glibc/glibc-i386-nosegneg.patch @@ -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 +--- 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 +--- 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 index 0000000000..828bf0edc6 --- /dev/null +++ b/src/patches/glibc/glibc-i386-timedrwlock.patch @@ -0,0 +1,97 @@ +2007-07-30 Jakub Jelinek + + * 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 index 0000000000..d435b2871f --- /dev/null +++ b/src/patches/glibc/glibc-i686-memset.patch @@ -0,0 +1,31 @@ +2006-02-21 Roland McGrath + + * sysdeps/i386/i686/memset.S: Fix treatment of unaligned pointer. + Reported by John Zulauf . + +--- 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 index 0000000000..05fd922969 --- /dev/null +++ b/src/patches/glibc/glibc-ia64-lib64.patch @@ -0,0 +1,92 @@ +2004-05-14 Jakub Jelinek + + * 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 ++#else ++#include ++#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 + + #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 ++#include +--- 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 ++#else ++#include ++#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 index 0000000000..a0ffdd3458 --- /dev/null +++ b/src/patches/glibc/glibc-ia64-libm-error.patch @@ -0,0 +1,35 @@ +2005-08-19 H.J. Lu + + * 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 index 0000000000..f9df4d4c3b --- /dev/null +++ b/src/patches/glibc/glibc-ia64-mcount.patch @@ -0,0 +1,30 @@ +2005-03-21 David Mosberger + + * 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 index 0000000000..25457973e1 --- /dev/null +++ b/src/patches/glibc/glibc-ia64-post-upgrade-hack.patch @@ -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 index 0000000000..4d78ebeb75 --- /dev/null +++ b/src/patches/glibc/glibc-ia64-shmatt_t.patch @@ -0,0 +1,25 @@ +2005-11-19 Jakub Jelinek + + * 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 index 0000000000..a7243e55c9 --- /dev/null +++ b/src/patches/glibc/glibc-innetgr-leak.patch @@ -0,0 +1,35 @@ +2005-09-24 Jakub Jelinek + + * 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 index 0000000000..0e586da141 --- /dev/null +++ b/src/patches/glibc/glibc-innetgr-thread-safety.patch @@ -0,0 +1,411 @@ +2005-09-09 Jakub Jelinek + + * 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 + + * 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 + #include + #include + #include +@@ -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) + } + } + ++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 + #include + #include ++#include + #include + #include + #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 index 0000000000..1d60cb640e --- /dev/null +++ b/src/patches/glibc/glibc-ld-library-path-DST.patch @@ -0,0 +1,33 @@ +2006-08-28 Ulrich Drepper + + * 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 index 0000000000..2711bf3512 --- /dev/null +++ b/src/patches/glibc/glibc-ld_debug-conflicts.patch @@ -0,0 +1,19 @@ +2005-10-26 Jakub Jelinek + + * 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 . + +--- 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 index 0000000000..592362f5d6 --- /dev/null +++ b/src/patches/glibc/glibc-ldconfig-prelink.patch @@ -0,0 +1,28 @@ +2005-12-27 Jakub Jelinek + + * 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 index 0000000000..9c228c1e33 --- /dev/null +++ b/src/patches/glibc/glibc-lddlibc4.patch @@ -0,0 +1,13 @@ +2005-09-20 Roland McGrath + + * 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 index 0000000000..abdd241fb2 --- /dev/null +++ b/src/patches/glibc/glibc-linuxthreads-atomic_h.patch @@ -0,0 +1,66 @@ +2006-02-23 Jakub Jelinek + + * 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 index 0000000000..5b18b98449 --- /dev/null +++ b/src/patches/glibc/glibc-loadarchive-leak.patch @@ -0,0 +1,20 @@ +2005-09-09 Jakub Jelinek + + [BZ #1318] + * locale/loadarchive.c (_nl_load_locale_from_archive): Free + normalized_codeset even if p was already normalized. + Reported by Jaroslav Snajdr . + +--- 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 index 0000000000..c5a4292943 --- /dev/null +++ b/src/patches/glibc/glibc-localealias-leak.patch @@ -0,0 +1,33 @@ +2005-08-19 Bruno Haible + + * 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 index 0000000000..94c39fb503 --- /dev/null +++ b/src/patches/glibc/glibc-madvise-hidden.patch @@ -0,0 +1,24 @@ +2007-04-19 Ulrich Drepper + + * 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 +--- 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 index 0000000000..f02a9e3d08 --- /dev/null +++ b/src/patches/glibc/glibc-nan.patch @@ -0,0 +1,24 @@ +2006-01-04 Joseph S. Myers + + * 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 index 0000000000..805d180d07 --- /dev/null +++ b/src/patches/glibc/glibc-nis+-batch.patch @@ -0,0 +1,5381 @@ +2006-05-01 Ulrich Drepper + + * 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 + + * 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 + + * 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 + + * 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 + + * nis/nss_nisplus/nisplus-netgrp.c: Cleanups. + +2006-04-15 Ulrich Drepper + + * 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 + + * 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 + + * 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 + + * 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 + #include + +-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 +-#include +-#include +-#include +-#include +-#include +- + #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 +-/* The following is an ugly trick to avoid a prototype declaration for +- _nss_nis_endgrent. */ +-#define _nss_nis_endgrent _nss_nis_endgrent_XXX +-#include +-#undef _nss_nis_endgrent + #include + #include ++#include ++#include + #include + #include + #include + #include + + #include "nss-nis.h" ++#include + + /* 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 + + #include "nss-nis.h" ++#include + + /* Get the declaration of the parser function. */ + #define ENTNAME grent +@@ -37,47 +38,6 @@ + #define EXTERN_PARSER + #include + +-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 +-/* The following is an ugly trick to avoid a prototype declaration for +- _nss_nis_endpwent. */ +-#define _nss_nis_endpwent _nss_nis_endpwent_XXX +-#include +-#undef _nss_nis_endpwent ++#include + #include + #include ++#include ++#include + #include + #include + #include + #include + + #include "nss-nis.h" ++#include + + /* 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 + + #include "nss-nis.h" ++#include + + + /* 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 + ++ + 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 ++ + + __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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++ ++/* 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 ++ ++ = 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 index 0000000000..93f5da6ac6 --- /dev/null +++ b/src/patches/glibc/glibc-nis+-batch2.patch @@ -0,0 +1,52 @@ +2006-05-18 Jakub Jelinek + + * 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 index 0000000000..9cb65656cf --- /dev/null +++ b/src/patches/glibc/glibc-nis+-findserver.patch @@ -0,0 +1,193 @@ +2006-08-07 Jakub Jelinek + Ulrich Drepper + + * 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 + + * 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 index 0000000000..09b6999103 --- /dev/null +++ b/src/patches/glibc/glibc-nis+-getenv.patch @@ -0,0 +1,32 @@ +2006-12-05 Jakub Jelinek + + * nis/nis_subr.c (nis_getnames): Revert last change. + +2006-10-11 Jakub Jelinek + + * 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 index 0000000000..bc3cf6f7ee --- /dev/null +++ b/src/patches/glibc/glibc-nis+-getnames.patch @@ -0,0 +1,338 @@ +2006-06-16 Ulrich Drepper + + * nis/nis_subr.c (nis_getnames): Fix the implementation to better + match what Solaris does. + +2006-05-25 Ulrich Drepper + + * 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 index 0000000000..34e553435c --- /dev/null +++ b/src/patches/glibc/glibc-nis+-leaks.patch @@ -0,0 +1,373 @@ +2006-05-04 Ulrich Drepper + + * 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 index 0000000000..e9096f4ee9 --- /dev/null +++ b/src/patches/glibc/glibc-nis+-leaks2.patch @@ -0,0 +1,15 @@ +2006-05-17 Jakub Jelinek + + * 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 index 0000000000..93d5ed3c6f --- /dev/null +++ b/src/patches/glibc/glibc-nis+-parent.patch @@ -0,0 +1,1882 @@ +2006-05-23 Ulrich Drepper + + * 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 + + * 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 + + * 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 + + * 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 + + * nis/nis_call.c (rec_dirsearch): Little optimization: pull + nis_free_directory forward to avoid duplication. + +2006-05-17 Ulrich Drepper + + * 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 ++ + #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 + + 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 + #include "nis_xdr.h" + #include "nis_intern.h" ++#include ++ + + 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 + #include + #include + + #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 + #include + +-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 ++#include ++#include + + + __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 ++#include ++#include + + + __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 index 0000000000..c118fa228b --- /dev/null +++ b/src/patches/glibc/glibc-nis+.patch @@ -0,0 +1,4601 @@ +2006-03-24 Jakub Jelinek + + * 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 + + * nis/ypclnt.c (yperr_string, ypbinderr_string): Add N_() + around string literals. + +2005-12-08 Ulrich Drepper + + * nis/nis_call.c (inetstr2int): Optimize. + +2005-12-08 Jakub Jelinek + + * 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 + + * nis/nis_table.c (nis_list): Fix memory handling in error case. + +2005-12-07 Ulrich Drepper + + * 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 + + * 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 + + * 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 + + * nis/nis_table.c (nis_list): Add more free calls in error cases. + +2005-11-26 Ulrich Drepper + + * 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 + #include + #include + #include +@@ -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 +-#include ++#include + #include +-#include +-#include ++#include ++#include + #include ++#include ++#include + #include +-#include + #include ++#include ++#include + + #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 + #include + #include + #include +@@ -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 +-#include +-#include ++#include + #include ++#include ++#include ++#include + #include +-#include + #include +-#include ++#include + #include ++#include + + #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 +-#include +-#include ++#include + #include ++#include ++#include ++#include + #include + #include + #include +-#include + #include ++#include + + #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 +-#include ++#include + #include ++#include + #include ++#include + #include +-#include + #include ++#include + + #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 + #include + #include + #include +@@ -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 +-#include ++#include + #include ++#include ++#include + #include +-#include + #include + #include ++#include + + #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 +-#include ++#include + #include ++#include + #include ++#include + #include +-#include + #include ++#include + + #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 index 0000000000..934d2d66f1 --- /dev/null +++ b/src/patches/glibc/glibc-nis-getservbyname.patch @@ -0,0 +1,16 @@ +2007-01-13 Ulrich Drepper + + * 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 index 0000000000..fa46577bf8 --- /dev/null +++ b/src/patches/glibc/glibc-nis-publickey.patch @@ -0,0 +1,16 @@ +2005-10-28 Thorsten Kukuk + + * 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 index 0000000000..db6080f2c9 --- /dev/null +++ b/src/patches/glibc/glibc-nis_leaf_of_r-0.patch @@ -0,0 +1,15 @@ +2005-08-15 Jakub Jelinek + + * 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 index 0000000000..66fa50cf3b --- /dev/null +++ b/src/patches/glibc/glibc-nonnull.patch @@ -0,0 +1,20 @@ +2007-05-10 Ulrich Drepper + + * 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 + ++/* 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 index 0000000000..ea490ef28c --- /dev/null +++ b/src/patches/glibc/glibc-nptl-cancel-init.patch @@ -0,0 +1,18 @@ +2005-11-17 Jakub Jelinek + + * 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 index 0000000000..48951ea5e8 --- /dev/null +++ b/src/patches/glibc/glibc-nptl-check.patch @@ -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 + #include + #include "kernel-features.h" ++#include + + #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 index 0000000000..389d4497c8 --- /dev/null +++ b/src/patches/glibc/glibc-nptl-fork-cancel.patch @@ -0,0 +1,57 @@ +2006-04-08 Ulrich Drepper + + * 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 . + +--- 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 index 0000000000..000624cc61 --- /dev/null +++ b/src/patches/glibc/glibc-nptl-fork-getpid.patch @@ -0,0 +1,150 @@ +2006-07-31 Daniel Jacobowitz + + * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++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 index 0000000000..2a1a7bf552 --- /dev/null +++ b/src/patches/glibc/glibc-nptl-futex-wait.patch @@ -0,0 +1,27 @@ +2006-02-08 Jakub Jelinek + + * 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 index 0000000000..23fe2cf9bf --- /dev/null +++ b/src/patches/glibc/glibc-nptl-setxid-2.patch @@ -0,0 +1,213 @@ +2006-09-27 Daniel Jacobowitz + + [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 index 0000000000..61f383be05 --- /dev/null +++ b/src/patches/glibc/glibc-nptl-setxid.patch @@ -0,0 +1,263 @@ +2005-10-03 Jakub Jelinek + + * allocatestack.c (setxid_signal_thread): Add + INTERNAL_SYSCALL_DECL (err). + +2005-10-02 Jakub Jelinek + + * allocatestack.c (setxid_signal_thread): Need to use + atomic_compare_and_exchange_bool_acq. + +2005-10-01 Ulrich Drepper + Jakub Jelinek + + * 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 index 0000000000..eba2ced550 --- /dev/null +++ b/src/patches/glibc/glibc-nscd-EINTR.patch @@ -0,0 +1,177 @@ +2005-08-23 Ulrich Drepper + + * 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, ¬found, total)); ++ TEMP_FAILURE_RETRY (send (fd, ¬found, 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, ¬found, total)); ++ written = TEMP_FAILURE_RETRY (send (fd, ¬found, 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, ¬found, total)); ++ written = TEMP_FAILURE_RETRY (send (fd, ¬found, 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, ¬found, total)); ++ written = TEMP_FAILURE_RETRY (send (fd, ¬found, 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, ¬found, total)); ++ written = TEMP_FAILURE_RETRY (send (fd, ¬found, 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 index 0000000000..dd472c4776 --- /dev/null +++ b/src/patches/glibc/glibc-nscd-LFS-logging.patch @@ -0,0 +1,15 @@ +2005-09-20 Jakub Jelinek + + * 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 index 0000000000..0a2d588f1a --- /dev/null +++ b/src/patches/glibc/glibc-nscd-SIGHUP-disabled-cache.patch @@ -0,0 +1,27 @@ +2006-04-26 Jakub Jelinek + + * 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 index 0000000000..ce583fba34 --- /dev/null +++ b/src/patches/glibc/glibc-nscd-SIGHUP.patch @@ -0,0 +1,81 @@ +2006-07-02 Jakub Jelinek + + * 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 index 0000000000..9ee8ba2690 --- /dev/null +++ b/src/patches/glibc/glibc-nscd-addinitgroups.patch @@ -0,0 +1,39 @@ +2006-09-05 Jakub Jelinek + + * nscd/initgrcache.c (addinitgroupsX): Move any_success + decl before first goto out. + +2006-08-01 Ulrich Drepper + + [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 index 0000000000..aa88446228 --- /dev/null +++ b/src/patches/glibc/glibc-nscd-auto-propagate.patch @@ -0,0 +1,197 @@ +2006-04-27 Jakub Jelinek + + * nscd/nscd.conf: Fix a typo. + +2006-04-26 Ulrich Drepper + + * 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 + # persistent + # shared + # max-db-size ++# auto-propagate + # + # 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 index 0000000000..2257195c01 --- /dev/null +++ b/src/patches/glibc/glibc-nscd-db-checker.patch @@ -0,0 +1,298 @@ +2005-08-08 Ulrich Drepper + Jakub Jelinek + + * 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 index 0000000000..2ab5a16a27 --- /dev/null +++ b/src/patches/glibc/glibc-nscd-debug-verbose.patch @@ -0,0 +1,52 @@ +2005-08-16 Ulrich Drepper + + * 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 + #include + #include ++#include + #include + #include + #include +@@ -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 index 0000000000..822f485195 --- /dev/null +++ b/src/patches/glibc/glibc-nscd-fallocate.patch @@ -0,0 +1,36 @@ +2005-08-08 Ulrich Drepper + + * 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 + #include + #include ++#include + #include + #include + #include +@@ -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 index 0000000000..0e7160999f --- /dev/null +++ b/src/patches/glibc/glibc-nscd-getpw_r-retry.patch @@ -0,0 +1,17 @@ +2005-09-22 Ulrich Drepper + + [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 index 0000000000..6f2573a8d0 --- /dev/null +++ b/src/patches/glibc/glibc-nscd-hst-noalias.patch @@ -0,0 +1,19 @@ +2005-11-19 Ulrich Drepper + + * 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 index 0000000000..932f6bec94 --- /dev/null +++ b/src/patches/glibc/glibc-nscd-max-db-size.patch @@ -0,0 +1,217 @@ +2005-08-23 Ulrich Drepper + + * 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 + # persistent + # shared ++# max-db-size + # + # 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 index 0000000000..118f906067 --- /dev/null +++ b/src/patches/glibc/glibc-nscd-msync.patch @@ -0,0 +1,19 @@ +2005-08-08 Ulrich Drepper + + * 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 index 0000000000..3f65235b5a --- /dev/null +++ b/src/patches/glibc/glibc-nscd-paranoia.patch @@ -0,0 +1,52 @@ +2006-04-27 Ulrich Drepper + + * 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 index 0000000000..f86f83dc7c --- /dev/null +++ b/src/patches/glibc/glibc-nscd-stat64.patch @@ -0,0 +1,33 @@ +2005-08-16 Ulrich Drepper + + * 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 index 0000000000..b7dc0b07f5 --- /dev/null +++ b/src/patches/glibc/glibc-nscd-stats.patch @@ -0,0 +1,41 @@ +2005-08-08 Ulrich Drepper + + * 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 index 0000000000..d470c8eea0 --- /dev/null +++ b/src/patches/glibc/glibc-nsswitch_conf.patch @@ -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 index 0000000000..c1b4b6a594 --- /dev/null +++ b/src/patches/glibc/glibc-obstack_h-typo.patch @@ -0,0 +1,18 @@ +2005-09-12 Roland McGrath + + [BZ #1331] + * malloc/obstack.h [!__STDC__] (obstack_int_grow_fast): Fix misnamed + macro argument. + Reported by Matej Vela . + +--- 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 index 0000000000..cfad4c9070 --- /dev/null +++ b/src/patches/glibc/glibc-ppc-assume.patch @@ -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 ++ ++#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 index 0000000000..5d4942794e --- /dev/null +++ b/src/patches/glibc/glibc-ppc-fegetround.patch @@ -0,0 +1,19 @@ +2006-02-03 Jakub Jelinek + + * 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 index 0000000000..943712a7bd --- /dev/null +++ b/src/patches/glibc/glibc-ppc-libSegFault.patch @@ -0,0 +1,49 @@ +2006-09-16 Jakub Jelinek + + * 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 index 0000000000..28b9dd91b6 --- /dev/null +++ b/src/patches/glibc/glibc-ppc-strncmp.patch @@ -0,0 +1,230 @@ +2005-11-17 Steven Munroe + + [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 + + [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 index 0000000000..13c9490980 --- /dev/null +++ b/src/patches/glibc/glibc-prelink-dynamic-weak.patch @@ -0,0 +1,17 @@ +2006-10-02 Ulrich Drepper + + * 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 index 0000000000..b375df41b2 --- /dev/null +++ b/src/patches/glibc/glibc-printf-string-len.patch @@ -0,0 +1,22 @@ +2007-05-06 Ulrich Drepper + + * stdio-common/vfprintf.c (process_string_arg): Optimize + ridiculous precision in wide char code printing multi-byte string. + Reported by Jim Meyering . + +--- 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 index 0000000000..2ec5ad5dc2 --- /dev/null +++ b/src/patches/glibc/glibc-pthread_getattr_np.patch @@ -0,0 +1,22 @@ +2007-06-22 Jakub Jelinek + + * 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 index 0000000000..9f312a3253 --- /dev/null +++ b/src/patches/glibc/glibc-quota_h.patch @@ -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 index 0000000000..b8857f47b9 --- /dev/null +++ b/src/patches/glibc/glibc-readonly-area.patch @@ -0,0 +1,44 @@ +2005-10-17 Ulrich Drepper + + * sysdeps/unix/sysv/linux/readonly-area.c (__readonly_area): Also + allow EACCES errors when opening /proc for now. + +2005-10-06 Ulrich Drepper + + * 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 + #include + #include + #include +@@ -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 index 0000000000..a497ca7d4e --- /dev/null +++ b/src/patches/glibc/glibc-regex_h-STDC.patch @@ -0,0 +1,221 @@ +2005-09-06 Ulrich Drepper + + * include/regex.h: Remove use of _RE_ARGS. + +2005-08-20 Paul Eggert + + * 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 + + /* 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 + + /* 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 index 0000000000..4f2b11889c --- /dev/null +++ b/src/patches/glibc/glibc-resolv-send_vc.patch @@ -0,0 +1,17 @@ +2005-08-21 Ulrich Drepper + + * 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 index 0000000000..11f657d8f8 --- /dev/null +++ b/src/patches/glibc/glibc-rh168266.patch @@ -0,0 +1,246 @@ +2006-02-28 Roland McGrath + + * libio/genops.c: Include for __sched_yield decl. + +2006-02-23 Jakub Jelinek + + * sysdeps/generic/sched_yield.c (__sched_yield): Add libc_hidden_def. + * sysdeps/mach/sched_yield.c (__sched_yield): Likewise. + +2006-01-14 Jakub Jelinek + + * 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 + + * 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 + + * 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 ++#ifdef _LIBC ++#include ++#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 +--- 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 index 0000000000..95908f7d4e --- /dev/null +++ b/src/patches/glibc/glibc-rh178934.patch @@ -0,0 +1,337 @@ +2007-03-22 Jakub Jelinek + + * 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 + Ulrich Drepper + + * 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 + #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 + #include + #include ++#include + #include + #include + #include +@@ -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 ++#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 index 0000000000..69ec0dc98c --- /dev/null +++ b/src/patches/glibc/glibc-rh184086.patch @@ -0,0 +1,37 @@ +2006-07-19 Jakub Jelinek + + * 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 + #include ++#include + #include + #include + #include +@@ -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 index 0000000000..22f8eb28d0 --- /dev/null +++ b/src/patches/glibc/glibc-rh190259.patch @@ -0,0 +1,29 @@ +2006-04-30 Ulrich Drepper + + * 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 index 0000000000..e0af80c0e4 --- /dev/null +++ b/src/patches/glibc/glibc-rh191464.patch @@ -0,0 +1,250 @@ +2006-05-30 Jakub Jelinek + + * 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 + + * 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 index 0000000000..7d9f8c4fc1 --- /dev/null +++ b/src/patches/glibc/glibc-rh192072.patch @@ -0,0 +1,508 @@ +2006-07-31 Ulrich Drepper + + * 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 index 0000000000..7a27a7a194 --- /dev/null +++ b/src/patches/glibc/glibc-rh193631.patch @@ -0,0 +1,85 @@ +2006-06-04 Ulrich Drepper + + * 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 + #include "spawn_int.h" + #include ++#include + + + /* 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 ++#include ++ ++/* 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 index 0000000000..7b7ea89065 --- /dev/null +++ b/src/patches/glibc/glibc-rh193873.patch @@ -0,0 +1,158 @@ +2006-06-02 Jakub Jelinek + + * 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 , 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 ++#include ++#include ++#include ++ ++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 (®s, 0, sizeof (regs)); ++ ++ re_compile_pattern ("$", 1, &re); ++ ++ int ret = 0, r = re_search (&re, str1, 4, 0, 4, ®s); ++ if (r != 4) ++ { ++ printf ("First re_search returned %d\n", r); ++ ret = 1; ++ } ++ r = re_search (&re, str2, 4, 0, 4, ®s); ++ 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 index 0000000000..b04f247fb3 --- /dev/null +++ b/src/patches/glibc/glibc-rh194321.patch @@ -0,0 +1,81 @@ +2006-06-22 Ulrich Drepper + + * 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 index 0000000000..8d4711f2f9 --- /dev/null +++ b/src/patches/glibc/glibc-rh197790.patch @@ -0,0 +1,77 @@ +2006-08-31 Jakub Jelinek + + * 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 + + * 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 + + * 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 index 0000000000..078d761ec6 --- /dev/null +++ b/src/patches/glibc/glibc-rh197932.patch @@ -0,0 +1,93 @@ +2006-07-26 Gavin Romig-Koch + + * 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 + + * 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 + + 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 index 0000000000..c5620765e5 --- /dev/null +++ b/src/patches/glibc/glibc-rh201748.patch @@ -0,0 +1,18 @@ +2006-08-08 Jakub Jelinek + + * 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 index 0000000000..2fbcc2037e --- /dev/null +++ b/src/patches/glibc/glibc-rh201826.patch @@ -0,0 +1,24 @@ +2006-08-09 Jakub Jelinek + + * 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 index 0000000000..cb61a8e97f --- /dev/null +++ b/src/patches/glibc/glibc-rh202991.patch @@ -0,0 +1,207 @@ +2006-09-06 Jakub Jelinek + + * 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 , 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 ++#include ++#include ++ ++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 index 0000000000..7be81ac65e --- /dev/null +++ b/src/patches/glibc/glibc-rh203237.patch @@ -0,0 +1,32 @@ +2006-08-19 Ulrich Drepper + + * 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 index 0000000000..a60989cc65 --- /dev/null +++ b/src/patches/glibc/glibc-rh203728.patch @@ -0,0 +1,65 @@ +2007-03-15 Jakub Jelinek + + * locale/programs/ld-ctype.c (find_translit): Return NULL if ctype is + NULL. + +2006-08-28 Jakub Jelinek + + * 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 + + * locale/programs/ld-ctype.c (ctype_read): Better patch for read + failure. + +2006-08-24 Ulrich Drepper + + * 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 index 0000000000..d96391e55d --- /dev/null +++ b/src/patches/glibc/glibc-rh203915.patch @@ -0,0 +1,69 @@ +2006-08-24 Jakub Jelinek + + * 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 index 0000000000..1b77ff91a9 --- /dev/null +++ b/src/patches/glibc/glibc-rh204122.patch @@ -0,0 +1,98 @@ +2006-08-28 Jakub Jelinek + + * 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 index 0000000000..7f50bfe309 --- /dev/null +++ b/src/patches/glibc/glibc-rh205113.patch @@ -0,0 +1,42 @@ +2006-09-04 Jakub Jelinek + + * 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 index 0000000000..5b150faad4 --- /dev/null +++ b/src/patches/glibc/glibc-rh206483.patch @@ -0,0 +1,45 @@ +2006-10-10 Ulrich Drepper + + * 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 index 0000000000..357f129e11 --- /dev/null +++ b/src/patches/glibc/glibc-rh206639.patch @@ -0,0 +1,153 @@ +2006-09-19 Ulrich Drepper + + * 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 + + * 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 ++#include ++ ++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 ++#include ++ ++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 index 0000000000..469ba65c42 --- /dev/null +++ b/src/patches/glibc/glibc-rh207928.patch @@ -0,0 +1,89 @@ +2006-10-02 Jakub Jelinek + + * 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 index 0000000000..b204e21ecb --- /dev/null +++ b/src/patches/glibc/glibc-rh208203.patch @@ -0,0 +1,417 @@ +2006-10-06 Ulrich Drepper + + * 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 + + * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "nss-nisplus.h" ++#include "nisplus-parser.h" ++#include ++#include ++#include ++ ++#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 index 0000000000..fd9489de9a --- /dev/null +++ b/src/patches/glibc/glibc-rh210748-workaround.patch @@ -0,0 +1,80 @@ +2007-01-15 Jakub Jelinek + + * 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 index 0000000000..e6ff0ca19d --- /dev/null +++ b/src/patches/glibc/glibc-rh211116.patch @@ -0,0 +1,157 @@ +2006-10-17 Jakub Jelinek + + * 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 , 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 ++#include ++#include ++#include ++#include ++#include ++ ++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 index 0000000000..17f2b3abef --- /dev/null +++ b/src/patches/glibc/glibc-rh215572.patch @@ -0,0 +1,18 @@ +2006-11-14 Jakub Jelinek + + * 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 index 0000000000..45b5c3f893 --- /dev/null +++ b/src/patches/glibc/glibc-rh218782.patch @@ -0,0 +1,50 @@ +2006-12-09 Jakub Jelinek + + * 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 index 0000000000..6d146e7be7 --- /dev/null +++ b/src/patches/glibc/glibc-rh218802.patch @@ -0,0 +1,82 @@ +2006-12-09 Jakub Jelinek + + * 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 ++#include ++#include ++ ++ ++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 index 0000000000..decdd8cecd --- /dev/null +++ b/src/patches/glibc/glibc-rh219145.patch @@ -0,0 +1,38 @@ +2006-12-19 Jakub Jelinek + + * 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 ++#include + #include + #include + #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 index 0000000000..fe573c984a --- /dev/null +++ b/src/patches/glibc/glibc-rh220621.patch @@ -0,0 +1,26 @@ +2006-12-22 Gavin Romig-Koch + + * 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 index 0000000000..cdce9b2471 --- /dev/null +++ b/src/patches/glibc/glibc-rh225315.patch @@ -0,0 +1,1104 @@ +2007-01-31 Jakub Jelinek + + * 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 + #include + #include ++#include + #include + #include + #include +@@ -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 index 0000000000..7a57513abf --- /dev/null +++ b/src/patches/glibc/glibc-rh227016.patch @@ -0,0 +1,192 @@ +2006-08-24 Ulrich Drepper + + * 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 + + [BZ #2683] + * elf/dl-addr.c (_dl_addr): Don't match undefined references. + +2005-08-30 Jakub Jelinek + Alan Modra + + * 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 ++ ++/* 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 ++#include ++#include ++ ++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 index 0000000000..487064bd03 --- /dev/null +++ b/src/patches/glibc/glibc-rh228103.patch @@ -0,0 +1,17 @@ +2007-02-09 Jakub Jelinek + + * 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 index 0000000000..4d3ff9399b --- /dev/null +++ b/src/patches/glibc/glibc-rh228697.patch @@ -0,0 +1,1934 @@ +2007-11-10 Ulrich Drepper + + * crypt/sha256-crypt.c: Fix a comment. + * crypt/sha512-crypt.c: Likewise. + +2007-10-28 Ulrich Drepper + + [BZ #5204] + * crypt/sha256c-test.c: Define TIMEOUT to 6 for ancient hardware. + * crypt/sha512c-test.c: Likewise. + +2007-09-19 Ulrich Drepper + + * 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 , 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 ++#include ++#include ++#include ++#include ++#include ++ ++#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 , 2007. */ ++ ++#ifdef HAVE_CONFIG_H ++# include ++#endif ++ ++#include ++#include ++#include ++#include ++ ++#include "sha256.h" ++ ++#if __BYTE_ORDER == __LITTLE_ENDIAN ++# ifdef _LIBC ++# include ++# 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 ++#include ++#include ++ ++ ++/* 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 ++#include ++#include ++ ++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 ++#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 , 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 ++#include ++#include ++#include ++#include ++#include ++ ++#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 , 2007. */ ++ ++#ifdef HAVE_CONFIG_H ++# include ++#endif ++ ++#include ++#include ++#include ++#include ++ ++#include "sha512.h" ++ ++#if __BYTE_ORDER == __LITTLE_ENDIAN ++# ifdef _LIBC ++# include ++# 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 ++#include ++#include ++ ++ ++/* 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 ++#include ++#include ++ ++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 ++#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 index 0000000000..b88ec5c0d4 --- /dev/null +++ b/src/patches/glibc/glibc-rh230168.patch @@ -0,0 +1,229 @@ +2007-04-25 Jakub Jelinek + + * sysdeps/unix/sysv/linux/check_pf.c (make_request): Return -1 instead + of 0 after the out_fail label. + +2007-03-18 Jakub Jelinek + + * nscd/gai.c: Include alloca.h. + (__libc_use_alloca): Define. + +2007-03-15 Jakub Jelinek + + * 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 + + * 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 + + * 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 + #include + #include + #include +@@ -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 + /* 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 + diff --git a/src/patches/glibc/glibc-rh230197.patch b/src/patches/glibc/glibc-rh230197.patch new file mode 100644 index 0000000000..64d810fa77 --- /dev/null +++ b/src/patches/glibc/glibc-rh230197.patch @@ -0,0 +1,22 @@ +2007-02-25 Ulrich Drepper + + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Reset refcntr in + new thread, don't just decrement it. + Patch by Suzuki K P . + +--- 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 index 0000000000..4fb96389cc --- /dev/null +++ b/src/patches/glibc/glibc-rh233460.patch @@ -0,0 +1,725 @@ +2007-04-05 Jakub Jelinek + + * nis/nis_call.c (__nisfind_server): Replace (*dir)->do_servers + with obj->do_servers after first_shoot. + +2007-03-01 Jakub Jelinek + + * 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 + #include + #include ++#include ++#include + #include + #include ++#include + + #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, ++ ¤t_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 index 0000000000..cf44455a84 --- /dev/null +++ b/src/patches/glibc/glibc-rh235229.patch @@ -0,0 +1,225 @@ +2007-04-06 Jakub Jelinek + + * 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 , 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, + ¤t_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 index 0000000000..d2538d72c3 --- /dev/null +++ b/src/patches/glibc/glibc-rh237711.patch @@ -0,0 +1,69 @@ +2007-05-07 Ulrich Drepper + Jakub Jelinek + + * 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 index 0000000000..ff22dd7965 --- /dev/null +++ b/src/patches/glibc/glibc-rh238431.patch @@ -0,0 +1,41 @@ +2007-04-30 Jakub Jelinek + + * 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 index 0000000000..1d72657cec --- /dev/null +++ b/src/patches/glibc/glibc-rh247788.patch @@ -0,0 +1,133 @@ +2007-08-02 Jakub Jelinek + + * 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 + + * 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 + + * 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 index 0000000000..55eea12672 --- /dev/null +++ b/src/patches/glibc/glibc-rh248281.patch @@ -0,0 +1,132 @@ +2007-07-16 Jakub Jelinek + + * 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 ++#include ++#include ++ ++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 index 0000000000..3449462e26 --- /dev/null +++ b/src/patches/glibc/glibc-rh254115.patch @@ -0,0 +1,35 @@ +2007-08-17 Jakub Jelinek + + * 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 index 0000000000..9733f2acce --- /dev/null +++ b/src/patches/glibc/glibc-rh339821.patch @@ -0,0 +1,17 @@ +2007-10-18 Ulrich Drepper + + * 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 . + +--- 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 index 0000000000..8a24fa7184 --- /dev/null +++ b/src/patches/glibc/glibc-rh346321.patch @@ -0,0 +1,36 @@ +2008-01-05 Jakub Jelinek + + [BZ #5112] + * nscd/connections.c (restart): Fix condition. + +2007-10-05 Ulrich Drepper + + [BZ #5112] + * nscd/connections.c (restart): Don't resync if database is + disabled. Patch mostly by Brian De Wolf . + +--- 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 index 0000000000..ee1a3dc3e8 --- /dev/null +++ b/src/patches/glibc/glibc-rh385601.patch @@ -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 + #include ++#include + + 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 ++#include + #ifdef HAVE_LIBIDN + # include + #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 ++#include + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -30,16 +32,30 @@ + #include + #include + +-#include "kernel-features.h" ++#include ++#include ++ ++ ++#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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++ ++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 + #include + #include ++#include ++#include ++#include ++#include + + #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 ++#include ++#include ++ ++/* 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 ++#include ++#include ++ ++/* 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 + #include ++#include + + /* 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 index 0000000000..b3629ca650 --- /dev/null +++ b/src/patches/glibc/glibc-rh403231.patch @@ -0,0 +1,186 @@ +2007-12-16 Ulrich Drepper + + * 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 ++#include ++#include ++#include ++ ++#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 index 0000000000..b2b81f1beb --- /dev/null +++ b/src/patches/glibc/glibc-rh405781.patch @@ -0,0 +1,21 @@ +2007-12-17 Ulrich Drepper + + * 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 index 0000000000..d15ff8ef09 --- /dev/null +++ b/src/patches/glibc/glibc-rh428859.patch @@ -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 index 0000000000..ecfe51e19d --- /dev/null +++ b/src/patches/glibc/glibc-rh434601.patch @@ -0,0 +1,18 @@ +2008-03-11 Jakub Jelinek + + * 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 . + +--- 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 index 0000000000..7ae39e61f3 --- /dev/null +++ b/src/patches/glibc/glibc-rh437571.patch @@ -0,0 +1,469 @@ +2007-01-03 Jakub Jelinek + + * 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 + #include + #include + #include +@@ -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 , 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 index 0000000000..125247d354 --- /dev/null +++ b/src/patches/glibc/glibc-rh455360.patch @@ -0,0 +1,30 @@ +2008-07-15 Ulrich Drepper + + * 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 index 0000000000..b443083bb6 --- /dev/null +++ b/src/patches/glibc/glibc-rh461481.patch @@ -0,0 +1,96 @@ +2008-09-12 Flavio Leitner + Ulrich Drepper + + * 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 index 0000000000..c277ec5b24 --- /dev/null +++ b/src/patches/glibc/glibc-rh464146.patch @@ -0,0 +1,27 @@ +2008-09-22 Deborah S. Townsend + + * 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 index 0000000000..d5e52be109 --- /dev/null +++ b/src/patches/glibc/glibc-rh467309.patch @@ -0,0 +1,140 @@ +2008-10-17 Jakub Jelinek + + * 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 + + * 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 ++#include ++ ++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 ++ ++#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 index 0000000000..faf4ffb913 --- /dev/null +++ b/src/patches/glibc/glibc-rh470781.patch @@ -0,0 +1,23 @@ +2008-10-30 Ulrich Drepper + + * 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 index 0000000000..c3d1b3842d --- /dev/null +++ b/src/patches/glibc/glibc-rtkaio-update.patch @@ -0,0 +1,1735 @@ +2006-05-11 Jakub Jelinek + + * 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 , 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 ++#include ++#include ++ ++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 +--- 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 +--- 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 +--- 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 + #include + #include ++#include ++#include ++#include + + 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 +--- 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 +--- 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 , 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 +--- 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 , 1997. +@@ -34,6 +34,28 @@ + #include + #include + #include ++#include ++ ++#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, ¶m); + 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 +--- 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 +--- 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 +--- 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 +--- 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 +--- 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 +--- 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 +--- 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 +--- 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 +--- 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 +--- 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 ++#include ++#include ++#include ++#include ++#include ++#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 , 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#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 ++ ++ ++/* 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 +--- 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 ++#include ++#include ++#include ++#include ++#include ++#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 +--- 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 ++#include ++#include ++#include ++#include ++#include ++#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 , 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 ++#include ++#include ++#include ++#include ++#include ++#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 +--- 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 , 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#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 ++ ++ ++/* 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 index 0000000000..0358ea5a8b --- /dev/null +++ b/src/patches/glibc/glibc-s390-setjmp.patch @@ -0,0 +1,16 @@ +2006-01-02 Jakub Jelinek + + * 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 index 0000000000..de6c07b4ad --- /dev/null +++ b/src/patches/glibc/glibc-scalb-namespace.patch @@ -0,0 +1,25 @@ +2006-02-01 Jakub Jelinek + + * 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 index 0000000000..3e83f080c7 --- /dev/null +++ b/src/patches/glibc/glibc-sched_getaffinity.patch @@ -0,0 +1,27 @@ +2006-05-12 Jakub Jelinek + + * 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 + #include + #include ++#include + #include + #include + +@@ -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 index 0000000000..3457793bf1 --- /dev/null +++ b/src/patches/glibc/glibc-sem_timedwait.patch @@ -0,0 +1,164 @@ +2007-05-25 Ulrich Drepper + + * Makefile (tests): Add tst-sem10. + * tst-sem10.c: New file. + +2007-05-25 Ulrich Drepper + Jakub Jelinek + + * 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 , 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++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 index 0000000000..23f6587e33 --- /dev/null +++ b/src/patches/glibc/glibc-sigwait-EINTR.patch @@ -0,0 +1,34 @@ +2005-08-01 Ulrich Drepper + + * 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 index 0000000000..177a4d9de4 --- /dev/null +++ b/src/patches/glibc/glibc-sockatmark.patch @@ -0,0 +1,16 @@ +2005-09-17 Ulrich Drepper + + [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 index 0000000000..ff0a150042 --- /dev/null +++ b/src/patches/glibc/glibc-stdio-put-error.patch @@ -0,0 +1,85 @@ +2005-10-17 Ulrich Drepper + + * libio/oldfileops.c (_IO_old_file_xsputn): Fix last patch. + Return EOF not 0. + +2005-09-04 Ulrich Drepper + + * 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 ++#include ++#include ++#include ++#include ++ ++ ++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 index 0000000000..c05a9e55b2 --- /dev/null +++ b/src/patches/glibc/glibc-strtod--0.patch @@ -0,0 +1,148 @@ +2007-08-03 Jakub Jelinek + + * 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 ++#include ++#include ++#include ++#include ++ ++#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 index 0000000000..a6f37aa492 --- /dev/null +++ b/src/patches/glibc/glibc-strtod.patch @@ -0,0 +1,301 @@ +2006-12-11 Ulrich Drepper + + * 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 + + [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 ++#include ++#include ++ ++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 ++#include ++#include ++ ++ ++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 ++#include ++ ++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 ++#include ++#include ++#include ++ ++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 index 0000000000..f34d0cb89f --- /dev/null +++ b/src/patches/glibc/glibc-strxfrm.patch @@ -0,0 +1,149 @@ +2006-11-10 Jakub Jelinek + + * 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 + + * string/Makefile (tests): Add tst-strxfrm2. + * string/tst-strxfrm2.c: New file. + +2006-11-08 Jakub Jelinek + + * 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 ++#include ++#include ++ ++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 index 0000000000..cfb5196dce --- /dev/null +++ b/src/patches/glibc/glibc-sysconf-intel-caches.patch @@ -0,0 +1,76 @@ +2006-02-01 Ulrich Drepper + + * 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 index 0000000000..63e3a83c5a --- /dev/null +++ b/src/patches/glibc/glibc-tgmath-type.patch @@ -0,0 +1,142 @@ +2005-10-14 Ulrich Drepper + + [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 + + [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 , 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 ++#include ++#include ++#include ++ ++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 index 0000000000..00128db905 --- /dev/null +++ b/src/patches/glibc/glibc-tls-model-ie.patch @@ -0,0 +1,17 @@ +2005-09-22 Roland McGrath + + * elf/dl-tsd.c (__libc_dl_error_tsd): Use attribute_tls_model_ie for + static __thread variable. + From Alexandre Oliva + +--- 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 index 0000000000..584b3ceda1 --- /dev/null +++ b/src/patches/glibc/glibc-tst-initializers1.patch @@ -0,0 +1,55 @@ +2006-01-09 Roland McGrath + + * 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 index 0000000000..dc18755241 --- /dev/null +++ b/src/patches/glibc/glibc-tst-signal7.patch @@ -0,0 +1,78 @@ +2005-12-28 Ulrich Drepper + + * 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 , 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 ++#include ++#include ++#include ++ ++ ++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 index 0000000000..940abb7ed5 --- /dev/null +++ b/src/patches/glibc/glibc-tzdata-update.patch @@ -0,0 +1,596 @@ +2005-09-12 Jakub Jelinek + + * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#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 index 0000000000..3910f1c9e9 --- /dev/null +++ b/src/patches/glibc/glibc-wcstol-internal.patch @@ -0,0 +1,43 @@ +2006-03-16 Roland McGrath + + * 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 index 0000000000..e6333059cb --- /dev/null +++ b/src/patches/glibc/glibc-x86_64-gas-workaround.patch @@ -0,0 +1,31 @@ +2005-07-06 Jakub Jelinek + + * 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 index 0000000000..8e218bb1a2 --- /dev/null +++ b/src/patches/glibc/glibc-x86_64-pthread_once-align.patch @@ -0,0 +1,155 @@ +2005-10-14 Jakub Jelinek + Ulrich Drepper + + * 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 , 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 ++#include ++#include ++#include ++#include ++ ++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 index 0000000000..7d3e420db7 --- /dev/null +++ b/src/patches/glibc/glibc-xtrace-options.patch @@ -0,0 +1,17 @@ +2005-09-17 Ulrich Drepper + + [BZ #1053] + * debug/xtrace.sh: Add missing escape character in -? match. + Patch by Peter Breitenlohner . + +--- 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) -- 2.39.5