diff options
88 files changed, 2254 insertions, 582 deletions
diff --git a/ChangeLog b/ChangeLog index 474543f6d8..17172269a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,231 @@ +2007-01-17 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/fatal-prepare.h: Use PTHFCT_CALL to + demangle pointer. + * csu/libc-start.c: Likewise. + +2007-01-16 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/posix/system.c: Remove NO_WAITPID support, it cannot + really work anyway. + +2007-01-15 Ulrich Drepper <drepper@redhat.com> + + * nscd/connections.c (servinfo): Renamed to reqinfo. Change all + users. + (handle_request): Remove unnecessary tests. + + * nscd/cache.c (cache_add): Record the failure to add to the cache. + +2007-01-15 Jakub Jelinek <jakub@redhat.com> + + * soft-fp/op-common.h (FP_TRUNC): When truncating a NaN, clear + workbits in semi-raw fraction. + + * math/test-misc.c: Add new tests. + +2007-01-14 Steven Munroe <sjmunroe@us.ibm.com> + + * math/basic-test.c: Include test-skeleton.c. + (TEST_TRUNC): Define. + (truncdfsf_test, trunctfsf_test, trunctfdf_test): New. + (main): Rename to ... + (do_test): ...this. Run new tests. + (TEST_FUNCTION): Define. + +2006-10-05 Steven Munroe <sjmunroe@us.ibm.com> + Joe Kerian <jkerian@us.us.ibm.com> + + [BZ #2749] + * soft-fp/op-4.h (__FP_FRAC_SUB_3, __FP_FRAC_SUB_4): Correct borrow + handling for high words. + * soft-fp/op-common.h (_FP_OVERFLOW_SEMIRAW): Always set inexact + and overflow for infinity. + +2007-01-15 Ulrich Drepper <drepper@redhat.com> + + * nscd/connections.c (handle_request): Add a __builtin_expect. + + * nscd/connections.c (serv2db): Change type into structure which + also says whether this is a request for data. Renamed to + servinfo. All users changed. + (handle_request): Much simpler test whether we should search the cache. + + * nscd/connections.c (handle_request): Fix thinko in selinux test + invocation. + + * sysdeps/generic/ldsodefs.h: Define DL_LOOKUP_SCOPE_LOCK. + * elf/dl-lookup.c (add_dependency): If scope map is locked, unlock + it before getting dl_load_lock and then relock. + (_dl_lookup_symbol_x): Pass flags to add_dependency. + When rerunning _dl_lookup_symbol_x, compute symbol_scope again in + case we unlocked the scope. + * elf/dl-runtime.c (_dl_fixup): Pass DL_LOOKUP_SCOPE_LOCK to + _dl_lookup_symbol_x in case we locked the scope. + (_dl_profile_fixup): Likewise. + * elf/dl-sym.c (do_sym): In flags passed to call_dl_lookup, also + set DL_LOOKUP_SCOPE_LOCK. + +2007-01-13 Ulrich Drepper <drepper@redhat.com> + + * inet/Makefile: Define CFLAGS-getsrvbynm_r.c and + CFLAGS-getsrvbynpt_r.c. + * nscd/getsrvbynm_r.c: New file. + * nscd/getsrvbypt_r.c: New file. + * nscd/nscd_getserv_r.c: New file. + * nscd/servicescache.c: New file. + * nscd/Makefile (routines): Add nscd_getserv_r. + (nscd-modules): Add getsrvbynm_r, getsrvbypt_r, and servicescache. + Define CFLAGS-servicescache.c, CFLAGS-getsrvbynm_r.c, and + CFLAGS-getsrvbypt_r.c. + * nscd/cache.c (prune_cache): Rewrite to get re-add function from + table. Add entries for services database. + * nscd/connections.c (serv2str): Mark as const. Add entries for + services database. + (dbs): Add .reset_res and servdb initialization. + (serv2db): Add entries for services database. + (verify_persistent_db): Accept dbnr == servdb. + (invalidate_cache): Rewrite database name recognition to use a table. + Call res_init() if .reset_res is set for database. + (handle_request): Add code to handle services database. + * nscd/gai.c: Don't define __getservbyname_r. + * nscd/nscd-client.h (request_type): Remove LASTDBREQ, add + GETSERVBYNAME, GETSERVBYPORT, GETFDSERV. + (serv_response_header): Define. + (struct datahead): Add serv_response_header member. + * nscd/nscd.c (parse_opt): Rewrite parsing of -i parameter value + using table. + * nscd/nscd.conf: Add entries for services database. + * nscd/nscd.h: Adjust declaration of dbnames and serv2str. + Declare serv_iov_disabled. + Declare addservbyname, readdservbyname, addservbyport, and + readdservbyport. + * nscd/nscd_conf.c (dbnames): Mark as const. Add services entry. + (find_db): Fix error message. + * nscd/nscd_proto.h: Declare __nss_not_use_nscd_services, + __nscd_getservbyname_r, and __nscd_getservbyport_r. + * nscd/selinux.c (perms): Add entries for services database. + * nss/Versions: Export __nss_services_lookup with GLIBC_PRIVATE. + * nss/nsswitch.c (__nss_disable_nscd): Also disable services database. + + * nscd/grpcache.c: Remove obsolete code. Cleanups. + * nscd/hstcache.c: Likewise. + * nscd/pwdcache.c: Likewise. + + * nis/nss_nis/nis-service.c (_nss_nis_getservbyname_r): Correct + computation of keylen. + + * include/string.h: Only redefine strndupa if this is really for + libc code. + +2007-01-12 Ulrich Drepper <drepper@redhat.com> + + * nscd/nscd_gethst_r.c: Minor cleanups. + + * nscd/connections.c (handle_request): Check selinux permissions + for all non-admin commands. + + * sysdeps/i386/i486/bits/atomic.h: Define + atomic_compare_and_exchange_val_acq, + atomic_compare_and_exchange_bool_acq, and atomic_exchange_and_add + using __sync_* built-ins for gcc >= 4.1. + * sysdeps/x86_64/bits/atomic.h: Likewise. + + [BZ #3840] + * scripts/check-local-headers.sh: Restrict to testing .o.d, .os.d, + and .oS.d files. + +2007-01-05 Steven Munroe <sjmunroe@us.ibm.com> + + * stdlib/tst-makecontext.c: Include errno.h. Change main() + to do_test(). Define TEST_FUNCTION. Include test-skeleton.c. + (do_test): Check errno and exit(0) if ENOSYS. + +2007-01-11 Jakub Jelinek <jakub@redhat.com> + + * stdlib/strtod_l.c (____STRTOF_INTERNAL): Fix handling of multi-byte + thousands separators. + * stdlib/Makefile: Add rules to build and run tst-strtod4. + * stdlib/tst-strtod4.c: New test. + + [BZ #3855] + * stdlib/strtod_l.c (____STRTOF_INTERNAL): 0x. not followed by + hexadecimal digit should accept just the initial 0. + * stdlib/tst-strtod2.c (tests): New variable. + (do_test): Run several tests rather than just one. + +2007-01-11 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/i386/soft-fp/sfp-machine.h: Remove. + * sysdeps/x86_64/soft-fp/sfp-machine.h: Likewise. + +2007-01-10 Ulrich Drepper <drepper@redhat.com> + + * io/fts.c: Make sure fts_cur is always valid after return from + fts_read. + Patch by Miloslav Trmac <mitr@redhat.com>. + +2006-10-27 Richard Sandiford <richard@codesourcery.com> + + * elf/elf.h (R_MIPS_GLOB_DAT): Define. + (R_MIPS_NUM): Bump by 1. + +2007-01-03 Jakub Jelinek <jakub@redhat.com> + + * posix/execvp.c: Include alloca.h. + (allocate_scripts_argv): Renamed to... + (scripts_argv): ... this. Don't allocate buffer here nor count + arguments. + (execvp): Use alloca if possible. + * posix/Makefile: Add rules to build and run tst-vfork3 test. + * posix/tst-vfork3.c: New test. + +2007-01-03 Ulrich Drepper <drepper@redhat.com> + + * string/Makefile (tst-strxfrm2-ENV): Define. + * stdlib/Makefile (tst-strtod3-ENV): Define. + +2007-01-02 Ulrich Drepper <drepper@redhat.com> + + * posix/getconf.c: Update copyright year. + * nss/getent.c: Likewise. + * iconv/iconvconfig.c: Likewise. + * iconv/iconv_prog.c: Likewise. + * elf/ldconfig.c: Likewise. + * catgets/gencat.c: Likewise. + * csu/version.c: Likewise. + * elf/ldd.bash.in: Likewise. + * elf/sprof.c (print_version): Likewise. + * locale/programs/locale.c: Likewise. + * locale/programs/localedef.c: Likewise. + * nscd/nscd.c (print_version): Likewise. + * debug/xtrace.sh: Likewise. + * malloc/memusage.sh: Likewise. + * malloc/mtrace.pl: Likewise. + * debug/catchsegv.sh: Likewise. + +2006-12-24 Ulrich Drepper <drepper@redhat.com> + + * malloc/malloc.c (sYSMALLOc): Remove some unnecessary alignment + attempts. + +2006-12-23 Ulrich Drepper <drepper@redhat.com> + + * posix/wordexp.c: Remove some unnecessary tests. + +2006-12-22 Gavin Romig-Koch <gavin@redhat.com> + + * nis/nss_compat/compat-grp.c (internal_getgrgid_r): Don't + blacklist the group till after we look it up. + +2006-12-21 Ulrich Drepper <drepper@redhat.com> + + * include/atomic.h (atomic_forced_read): New macro. + +2006-12-20 SUGIOKA Toshinobu <sugioka@itonet.co.jp> + + * sysdeps/unix/sysv/linux/sh/bits/shm.h: New file. + 2006-12-19 Jakub Jelinek <jakub@redhat.com> * nss/getXXbyYY_r.c: Include atomic.h. @@ -39,7 +267,7 @@ [BZ #3747] * stdlib/jrand48_r.c (__jrand48_r): Make sure result is in the - [-231 .. 231) range. + [-2^31 .. 2^31) range. * stdlib/tst-rand48.c (main): Fix expected values for 64-bit targets. * stdlib/tst-rand48-2.c: New test. diff --git a/NEWS b/NEWS index f078f3cc63..a32179fe6a 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,5 @@ -GNU C Library NEWS -- history of user-visible changes. 2006-10-11 -Copyright (C) 1992-2002,2003,2004,2005,2006 Free Software Foundation, Inc. +GNU C Library NEWS -- history of user-visible changes. 2007-1-13 +Copyright (C) 1992-2006, 2007 Free Software Foundation, Inc. See the end for copying conditions. Please send GNU C library bug reports via <http://sources.redhat.com/bugzilla/> @@ -9,6 +9,8 @@ Version 2.6 * New Linux interfaces: epoll_pwait. +* nscd can now cache the services database. Implemented by Ulrich Drepper. + Version 2.5 diff --git a/catgets/gencat.c b/catgets/gencat.c index e72754d526..f5cbb8e1b3 100644 --- a/catgets/gencat.c +++ b/catgets/gencat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 1996-2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 1996. @@ -246,7 +246,7 @@ print_version (FILE *stream, struct argp_state *state) Copyright (C) %s Free Software Foundation, Inc.\n\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ -"), "2006"); +"), "2007"); fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); } diff --git a/csu/libc-start.c b/csu/libc-start.c index 634844759d..0ed993651e 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998-2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 1998-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 @@ -225,7 +225,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), { /* Remove the thread-local data. */ # ifdef SHARED - __libc_pthread_functions.ptr__nptl_deallocate_tsd (); + PTHFCT_CALL (ptr__nptl_deallocate_tsd, ()); # else extern void __nptl_deallocate_tsd (void) __attribute ((weak)); __nptl_deallocate_tsd (); @@ -235,7 +235,8 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), terminate the entire process. */ result = 0; # ifdef SHARED - unsigned int *const ptr = __libc_pthread_functions.ptr_nthreads; + unsigned int *ptr = __libc_pthread_functions.ptr_nthreads; + PTR_DEMANGLE (ptr); # else extern unsigned int __nptl_nthreads __attribute ((weak)); unsigned int *const ptr = &__nptl_nthreads; diff --git a/csu/version.c b/csu/version.c index 1b98c4a7e9..f7a8fb35e9 100644 --- a/csu/version.c +++ b/csu/version.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2002, 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 1992-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 @@ -25,7 +25,7 @@ static const char __libc_version[] = VERSION; static const char banner[] = "GNU C Library "RELEASE" release version "VERSION", by Roland McGrath et al.\n\ -Copyright (C) 2006 Free Software Foundation, Inc.\n\ +Copyright (C) 2007 Free Software Foundation, Inc.\n\ This is free software; see the source for copying conditions.\n\ There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\ PARTICULAR PURPOSE.\n\ diff --git a/debug/catchsegv.sh b/debug/catchsegv.sh index f4d971e34b..6f47fab42a 100755 --- a/debug/catchsegv.sh +++ b/debug/catchsegv.sh @@ -1,5 +1,6 @@ #! /bin/sh -# Copyright (C) 1998,1999,2001,2003,2004,2006 Free Software Foundation, Inc. +# Copyright (C) 1998,1999,2001,2003,2004,2006,2007 +# Free Software Foundation, Inc. # This file is part of the GNU C Library. # Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -39,7 +40,7 @@ if test $# -eq 0; then ;; --v | --ve | --ver | --vers | --versi | --versio | --version) echo 'catchsegv (GNU libc) @VERSION@' - echo 'Copyright (C) 2006 Free Software Foundation, Inc. + echo 'Copyright (C) 2007 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Written by Ulrich Drepper.' diff --git a/debug/xtrace.sh b/debug/xtrace.sh index 082db3f349..e8ffe2f420 100755 --- a/debug/xtrace.sh +++ b/debug/xtrace.sh @@ -1,5 +1,5 @@ #! @BASH@ -# Copyright (C) 1999, 2001-2004, 2005, 2006 Free Software Foundation, Inc. +# Copyright (C) 1999, 2001-2006, 2007 Free Software Foundation, Inc. # This file is part of the GNU C Library. # Contributed by Ulrich Drepper <drepper@gnu.org>, 1999. @@ -64,7 +64,7 @@ do_version() { printf $"Copyright (C) %s Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -" "2006" +" "2007" printf $"Written by %s. " "Ulrich Drepper" exit 0 diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 019278c9b0..a6a958419f 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -1,5 +1,5 @@ /* Look up a symbol in the loaded objects. - Copyright (C) 1995-2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1995-2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -25,6 +25,7 @@ #include <ldsodefs.h> #include <dl-hash.h> #include <dl-machine.h> +#include <sysdep-cancel.h> #include <bits/libc-lock.h> #include <tls.h> @@ -85,7 +86,7 @@ dl_new_hash (const char *s) /* Add extra dependency on MAP to UNDEF_MAP. */ static int internal_function -add_dependency (struct link_map *undef_map, struct link_map *map) +add_dependency (struct link_map *undef_map, struct link_map *map, int flags) { struct link_map **list; struct link_map *runp; @@ -98,8 +99,18 @@ add_dependency (struct link_map *undef_map, struct link_map *map) if (undef_map == map) return 0; - /* Make sure nobody can unload the object while we are at it. */ - __rtld_lock_lock_recursive (GL(dl_load_lock)); + /* Make sure nobody can unload the object while we are at it. + If we hold a scope lock drop it now to avoid ABBA locking problems. */ + if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0 && !RTLD_SINGLE_THREAD_P) + { + __rtld_mrlock_unlock (undef_map->l_scope_lock); + + __rtld_lock_lock_recursive (GL(dl_load_lock)); + + __rtld_mrlock_lock (undef_map->l_scope_lock); + } + else + __rtld_lock_lock_recursive (GL(dl_load_lock)); /* Avoid references to objects which cannot be unloaded anyway. */ if (map->l_type != lt_loaded @@ -226,9 +237,10 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, bump_num_relocations (); - /* No other flag than DL_LOOKUP_ADD_DEPENDENCY is allowed if we look - up a versioned symbol. */ - assert (version == NULL || flags == 0 || flags == DL_LOOKUP_ADD_DEPENDENCY); + /* No other flag than DL_LOOKUP_ADD_DEPENDENCY and DL_LOOKUP_SCOPE_LOCK + is allowed if we look up a versioned symbol. */ + assert (version == NULL || (flags & ~(DL_LOOKUP_ADD_DEPENDENCY + | DL_LOOKUP_SCOPE_LOCK)) == 0); size_t i = 0; if (__builtin_expect (skip_map != NULL, 0)) @@ -338,12 +350,13 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, runtime lookups. */ && (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0 /* Add UNDEF_MAP to the dependencies. */ - && add_dependency (undef_map, current_value.m) < 0) + && add_dependency (undef_map, current_value.m, flags) < 0) /* Something went wrong. Perhaps the object we tried to reference was just removed. Try finding another definition. */ return _dl_lookup_symbol_x (undef_name, undef_map, ref, - symbol_scope, version, type_class, - flags, skip_map); + (flags & DL_LOOKUP_SCOPE_LOCK) == 0 + ? symbol_scope : undef_map->l_scope, version, + type_class, flags, skip_map); /* The object is used. */ current_value.m->l_used = 1; diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c index afc99f6150..9ecf62b436 100644 --- a/elf/dl-runtime.c +++ b/elf/dl-runtime.c @@ -1,5 +1,5 @@ /* On-demand PLT fixup for shared objects. - Copyright (C) 1995-2002,2003,2004,2005,2006 Free Software Foundation, Inc. + Copyright (C) 1995-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 @@ -93,14 +93,20 @@ _dl_fixup ( version = NULL; } + /* We need to keep the scope around so do some locking. This is + not necessary for objects which cannot be unloaded or when + we are not using any threads (yet). */ + int flags = DL_LOOKUP_ADD_DEPENDENCY; if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P) - __rtld_mrlock_lock (l->l_scope_lock); + { + __rtld_mrlock_lock (l->l_scope_lock); + flags |= DL_LOOKUP_SCOPE_LOCK; + } - result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, - l->l_scope, version, ELF_RTYPE_CLASS_PLT, - DL_LOOKUP_ADD_DEPENDENCY, NULL); + result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope, + version, ELF_RTYPE_CLASS_PLT, flags, NULL); - if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P) + if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0) __rtld_mrlock_unlock (l->l_scope_lock); /* Currently result contains the base load address (or link map) @@ -181,15 +187,21 @@ _dl_profile_fixup ( version = NULL; } + /* We need to keep the scope around so do some locking. This is + not necessary for objects which cannot be unloaded or when + we are not using any threads (yet). */ + int flags = DL_LOOKUP_ADD_DEPENDENCY; if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P) - __rtld_mrlock_lock (l->l_scope_lock); + { + __rtld_mrlock_lock (l->l_scope_lock); + flags |= DL_LOOKUP_SCOPE_LOCK; + } - result = _dl_lookup_symbol_x (strtab + refsym->st_name, l, &defsym, - l->l_scope, version, - ELF_RTYPE_CLASS_PLT, - DL_LOOKUP_ADD_DEPENDENCY, NULL); + result = _dl_lookup_symbol_x (strtab + refsym->st_name, l, + &defsym, l->l_scope, version, + ELF_RTYPE_CLASS_PLT, flags, NULL); - if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P) + if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0) __rtld_mrlock_unlock (l->l_scope_lock); /* Currently result contains the base load address (or link map) diff --git a/elf/dl-sym.c b/elf/dl-sym.c index 88a5adb0d5..1c3ab5c877 100644 --- a/elf/dl-sym.c +++ b/elf/dl-sym.c @@ -1,5 +1,5 @@ /* Look up a symbol in a shared object loaded by `dlopen'. - Copyright (C) 1999,2000,2001,2002,2004,2006 Free Software Foundation, Inc. + Copyright (C) 1999-2002,2004,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -126,7 +126,7 @@ do_sym (void *handle, const char *name, void *who, args.name = name; args.map = match; args.vers = vers; - args.flags = flags | DL_LOOKUP_ADD_DEPENDENCY; + args.flags = flags | DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_SCOPE_LOCK; args.refp = &ref; const char *objname; diff --git a/elf/elf.h b/elf/elf.h index dae359778b..d27e5f085d 100644 --- a/elf/elf.h +++ b/elf/elf.h @@ -1,5 +1,5 @@ /* This file defines standard ELF types, structures, and macros. - Copyright (C) 1995-2003,2004,2005,2006 Free Software Foundation, Inc. + Copyright (C) 1995-2003,2004,2005,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -1511,8 +1511,9 @@ typedef struct #define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */ #define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */ #define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */ +#define R_MIPS_GLOB_DAT 51 /* Keep this the last entry. */ -#define R_MIPS_NUM 51 +#define R_MIPS_NUM 52 /* Legal values for p_type field of Elf32_Phdr. */ diff --git a/elf/ldconfig.c b/elf/ldconfig.c index 45a622288e..cb3b6c3b65 100644 --- a/elf/ldconfig.c +++ b/elf/ldconfig.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1999-2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 1999-2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Jaeger <aj@suse.de>, 1999. @@ -287,7 +287,7 @@ print_version (FILE *stream, struct argp_state *state) Copyright (C) %s Free Software Foundation, Inc.\n\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ -"), "2006"); +"), "2007"); fprintf (stream, gettext ("Written by %s.\n"), "Andreas Jaeger"); } diff --git a/elf/ldd.bash.in b/elf/ldd.bash.in index d1591a5785..05282fe99b 100644 --- a/elf/ldd.bash.in +++ b/elf/ldd.bash.in @@ -1,5 +1,5 @@ #! @BASH@ -# Copyright (C) 1996-2004, 2005, 2006 Free Software Foundation, Inc. +# Copyright (C) 1996-2004, 2005, 2006, 2007 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -39,7 +39,7 @@ while test $# -gt 0; do printf $"Copyright (C) %s Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -" "2006" +" "2007" printf $"Written by %s and %s. " "Roland McGrath" "Ulrich Drepper" exit 0 diff --git a/elf/sprof.c b/elf/sprof.c index e53a7ba7a3..01d27e1eff 100644 --- a/elf/sprof.c +++ b/elf/sprof.c @@ -1,5 +1,5 @@ /* Read and display shared object profiling data. - Copyright (C) 1997-2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1997-2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -357,7 +357,7 @@ Copyright (C) %s Free Software Foundation, Inc.\n\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ "), - "2006"); + "2007"); fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); } diff --git a/fedora/branch.mk b/fedora/branch.mk index 7e8e9318e6..2d72bfd8dd 100644 --- a/fedora/branch.mk +++ b/fedora/branch.mk @@ -3,5 +3,5 @@ glibc-branch := fedora glibc-base := HEAD DIST_BRANCH := devel COLLECTION := dist-fc7 -fedora-sync-date := 2006-12-19 18:04 UTC -fedora-sync-tag := fedora-glibc-20061219T1804 +fedora-sync-date := 2007-01-17 08:57 UTC +fedora-sync-tag := fedora-glibc-20070117T0857 diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in index 95d9ec51e7..8b2027346c 100644 --- a/fedora/glibc.spec.in +++ b/fedora/glibc.spec.in @@ -1,4 +1,4 @@ -%define glibcrelease 14 +%define glibcrelease 15 %define auxarches i586 i686 athlon sparcv9 alphaev6 %define xenarches i686 athlon %ifarch %{xenarches} @@ -46,7 +46,7 @@ Obsoletes: libc Prereq: basesystem, libgcc # This is for building auxiliary programs like memusage, nscd # For initial glibc bootstraps it can be commented out -BuildPreReq: gd-devel libpng-devel zlib-devel texinfo, libselinux-devel >= 1.17.10-1 +BuildPreReq: gd-devel libpng-devel zlib-devel texinfo, libselinux-devel >= 1.33.4-3 BuildPreReq: audit-libs-devel >= 1.1.3, sed >= 3.95, libcap-devel, gettext BuildPreReq: /bin/ps, /bin/kill, /bin/awk # This is to ensure that __frame_state_for is exported by glibc @@ -788,7 +788,7 @@ touch locale/programs/*-kw.h GCC=gcc GXX=g++ %ifarch %{ix86} -BuildFlags="-march=%{_target_cpu} -mtune=generic" +BuildFlags="-march=%{nptl_target_cpu} -mtune=generic" %endif %ifarch i686 BuildFlags="-march=i686 -mtune=generic" @@ -1378,7 +1378,7 @@ done %else mkdir -p $RPM_BUILD_ROOT/var/{db,run}/nscd -touch $RPM_BUILD_ROOT/var/{db,run}/nscd/{passwd,group,hosts} +touch $RPM_BUILD_ROOT/var/{db,run}/nscd/{passwd,group,hosts,services} touch $RPM_BUILD_ROOT/var/run/nscd/{socket,nscd.pid} %endif @@ -1517,9 +1517,11 @@ rm -f *.filelist* %attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/passwd %attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/group %attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/hosts +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/services %attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/passwd %attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/group %attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/hosts +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/services %ghost %config(missingok,noreplace) /etc/sysconfig/nscd %endif @@ -1544,6 +1546,19 @@ rm -f *.filelist* %endif %changelog +* Wed Jan 17 2007 Jakub Jelinek <jakub@redhat.com> 2.5.90-15 +- fix NIS getservbyname when proto is NULL +- fix nss_compat +group handling (#220658) +- cache services in nscd +- fix double free in fts_close (#222089) +- fix vfork+execvp memory leak (#221187) +- soft-fp fixes (BZ#2749) +- further strtod fixes (BZ#3855) +- make sure pthread_kill doesn't return EINVAL even if + the target thread exits in between pthread_kill ESRCH check + and the actual tgkill syscall (#220420) +- fix ABBA deadlock possibility in ld.so scope locking code + * Tue Dec 19 2006 Jakub Jelinek <jakub@redhat.com> 2.5.90-14 - fix {j,m}rand48{,_r} on 64-bit arches (BZ#3747) - handle power6x AT_PLATFORM (#216970) diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c index 77829971ad..84493af68f 100644 --- a/iconv/iconv_prog.c +++ b/iconv/iconv_prog.c @@ -1,5 +1,5 @@ /* Convert text in given files from the specified from-set to the to-set. - Copyright (C) 1998-2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1998-2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -426,7 +426,7 @@ print_version (FILE *stream, struct argp_state *state) Copyright (C) %s Free Software Foundation, Inc.\n\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ -"), "2006"); +"), "2007"); fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); } diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c index 59867f9015..7ff9b59e4a 100644 --- a/iconv/iconvconfig.c +++ b/iconv/iconvconfig.c @@ -1,5 +1,5 @@ /* Generate fastloading iconv module configuration files. - Copyright (C) 2000-2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2000-2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2000. @@ -395,7 +395,7 @@ print_version (FILE *stream, struct argp_state *state) Copyright (C) %s Free Software Foundation, Inc.\n\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ -"), "2006"); +"), "2007"); fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); } diff --git a/include/atomic.h b/include/atomic.h index ec1e9899f1..2ad8b5fcb7 100644 --- a/include/atomic.h +++ b/include/atomic.h @@ -497,6 +497,12 @@ #endif +#ifndef atomic_forced_read +# define atomic_forced_read(x) \ + ({ __typeof (x) __x; __asm ("" : "=r" (__x) : "0" (x)); __x; }) +#endif + + #ifndef atomic_delay # define atomic_delay() do { /* nothing */ } while (0) #endif diff --git a/include/string.h b/include/string.h index c196007dcb..f73bbf9f43 100644 --- a/include/string.h +++ b/include/string.h @@ -54,8 +54,9 @@ extern __typeof (strcasecmp_l) __strcasecmp_l; extern __typeof (strncasecmp_l) __strncasecmp_l; /* Alternative version which doesn't pollute glibc's namespace. */ -#undef strndupa -#define strndupa(s, n) \ +#ifndef NOT_IN_libc +# undef strndupa +# define strndupa(s, n) \ (__extension__ \ ({ \ __const char *__old = (s); \ @@ -64,6 +65,7 @@ extern __typeof (strncasecmp_l) __strncasecmp_l; __new[__len] = '\0'; \ (char *) memcpy (__new, __old, __len); \ })) +#endif libc_hidden_proto (__mempcpy) libc_hidden_proto (__stpcpy) diff --git a/inet/Makefile b/inet/Makefile index 075716fbeb..ad90b06199 100644 --- a/inet/Makefile +++ b/inet/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-2002, 2003, 2004, 2006 Free Software Foundation, Inc. +# Copyright (C) 1991-2006, 2007 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -79,6 +79,8 @@ CFLAGS-getrpcent_r.c = -fexceptions CFLAGS-getrpcent.c = -fexceptions CFLAGS-getservent_r.c = -fexceptions CFLAGS-getservent.c = -fexceptions +CFLAGS-getsrvbynm_r.c = -DUSE_NSCD=1 +CFLAGS-getsrvbypt_r.c = -DUSE_NSCD=1 CFLAGS-getprtent_r.c = -fexceptions CFLAGS-getprtent.c = -fexceptions CFLAGS-either_ntoh.c = -fexceptions diff --git a/io/fts.c b/io/fts.c index 532743fb3e..8e628b481d 100644 --- a/io/fts.c +++ b/io/fts.c @@ -376,12 +376,14 @@ fts_read(sp) } p = sp->fts_child; sp->fts_child = NULL; + sp->fts_cur = p; goto name; } /* Move to the next node on this level. */ next: tmp = p; if ((p = p->fts_link) != NULL) { + sp->fts_cur = p; free(tmp); /* @@ -394,7 +396,7 @@ next: tmp = p; return (NULL); } fts_load(sp, p); - return (sp->fts_cur = p); + return p; } /* @@ -420,11 +422,12 @@ next: tmp = p; name: t = sp->fts_path + NAPPEND(p->fts_parent); *t++ = '/'; memmove(t, p->fts_name, p->fts_namelen + 1); - return (sp->fts_cur = p); + return p; } /* Move up to the parent node. */ p = tmp->fts_parent; + sp->fts_cur = p; free(tmp); if (p->fts_level == FTS_ROOTPARENTLEVEL) { @@ -465,7 +468,7 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent); return (NULL); } p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; - return (sp->fts_cur = p); + return p; } /* diff --git a/locale/programs/locale.c b/locale/programs/locale.c index a03974e8a1..cc3082d48a 100644 --- a/locale/programs/locale.c +++ b/locale/programs/locale.c @@ -1,5 +1,5 @@ /* Implementation of the locale program according to POSIX 9945-2. - Copyright (C) 1995-1997, 1999-2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1995-1997, 1999-2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1995. @@ -275,7 +275,7 @@ print_version (FILE *stream, struct argp_state *state) Copyright (C) %s Free Software Foundation, Inc.\n\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ -"), "2006"); +"), "2007"); fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); } diff --git a/locale/programs/localedef.c b/locale/programs/localedef.c index 9c3acbebcc..04dcf8ee0d 100644 --- a/locale/programs/localedef.c +++ b/locale/programs/localedef.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995-2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 1995-2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1995. @@ -387,7 +387,7 @@ print_version (FILE *stream, struct argp_state *state) Copyright (C) %s Free Software Foundation, Inc.\n\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ -"), "2006"); +"), "2007"); fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); } diff --git a/malloc/malloc.c b/malloc/malloc.c index d15ed57bd7..6427608a79 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -2896,7 +2896,13 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av; is one SIZE_SZ unit larger than for normal chunks, because there is no following chunk whose prev_size field could be used. */ +#if 1 + /* See the front_misalign handling below, for glibc there is no + need for further alignments. */ + size = (nb + SIZE_SZ + pagemask) & ~pagemask; +#else size = (nb + SIZE_SZ + MALLOC_ALIGN_MASK + pagemask) & ~pagemask; +#endif tried_mmap = true; /* Don't try if size wraps around 0 */ @@ -2914,6 +2920,12 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av; address argument for later munmap in free() and realloc(). */ +#if 1 + /* For glibc, chunk2mem increases the address by 2*SIZE_SZ and + MALLOC_ALIGN_MASK is 2*SIZE_SZ-1. Each mmap'ed area is page + aligned and therefore definitely MALLOC_ALIGN_MASK-aligned. */ + assert (((INTERNAL_SIZE_T)chunk2mem(mm) & MALLOC_ALIGN_MASK) == 0); +#else front_misalign = (INTERNAL_SIZE_T)chunk2mem(mm) & MALLOC_ALIGN_MASK; if (front_misalign > 0) { correction = MALLOC_ALIGNMENT - front_misalign; @@ -2921,10 +2933,12 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av; p->prev_size = correction; set_head(p, (size - correction) |IS_MMAPPED); } - else { - p = (mchunkptr)mm; - set_head(p, size|IS_MMAPPED); - } + else +#endif + { + p = (mchunkptr)mm; + set_head(p, size|IS_MMAPPED); + } /* update statistics */ diff --git a/malloc/memusage.sh b/malloc/memusage.sh index ad833523f2..67af4998ca 100755 --- a/malloc/memusage.sh +++ b/malloc/memusage.sh @@ -1,5 +1,5 @@ #! @BASH@ -# Copyright (C) 1999-2004, 2005, 2006 Free Software Foundation, Inc. +# Copyright (C) 1999-2004, 2005, 2006, 2007 Free Software Foundation, Inc. # This file is part of the GNU C Library. # Contributed by Ulrich Drepper <drepper@gnu.org>, 1999. @@ -71,7 +71,7 @@ do_version() { printf $"Copyright (C) %s Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -" "2006" +" "2007" printf $"Written by %s. " "Ulrich Drepper" exit 0 diff --git a/malloc/mtrace.pl b/malloc/mtrace.pl index 8a0fbc7e95..280b469d92 100644 --- a/malloc/mtrace.pl +++ b/malloc/mtrace.pl @@ -1,7 +1,7 @@ #! @PERL@ eval "exec @PERL@ -S $0 $*" if 0; -# Copyright (C) 1997-2004, 2005, 2006 Free Software Foundation, Inc. +# Copyright (C) 1997-2004, 2005, 2006, 2007 Free Software Foundation, Inc. # This file is part of the GNU C Library. # Contributed by Ulrich Drepper <drepper@gnu.org>, 1997. # Based on the mtrace.awk script. @@ -45,7 +45,7 @@ arglist: while (@ARGV) { $ARGV[0] eq "--vers" || $ARGV[0] eq "--versi" || $ARGV[0] eq "--versio" || $ARGV[0] eq "--version") { print "mtrace (GNU $PACKAGE) $VERSION\n"; - print "Copyright (C) 2006 Free Software Foundation, Inc.\n"; + print "Copyright (C) 2007 Free Software Foundation, Inc.\n"; print "This is free software; see the source for copying conditions. There is NO\n"; print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"; print "Written by Ulrich Drepper <drepper\@gnu.org>\n"; diff --git a/math/basic-test.c b/math/basic-test.c index e42c014572..e48a3ae4e0 100644 --- a/math/basic-test.c +++ b/math/basic-test.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1999 Free Software Foundation, Inc. +/* Copyright (C) 1999, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Jaeger <aj@suse.de>, 1999. @@ -44,7 +44,7 @@ NAME (void) \ \ zero_var = 0.0; \ one_var = 1.0; \ - NaN_var = zero_var/zero_var; \ + NaN_var = zero_var / zero_var; \ Inf_var = one_var / zero_var; \ \ (void) &zero_var; \ @@ -103,21 +103,51 @@ NAME (void) \ check (#FLOAT " isinf (-HUGE_VALx) == -1", isinf (x1) == -1); \ } +#define TEST_TRUNC(NAME, FLOAT, DOUBLE) \ +void \ +NAME (void) \ +{ \ + volatile DOUBLE Inf_var, NaN_var, zero_var, one_var; \ + FLOAT x1, x2; \ + \ + zero_var = 0.0; \ + one_var = 1.0; \ + NaN_var = zero_var / zero_var; \ + Inf_var = one_var / zero_var; \ + \ + (void) &NaN_var; \ + (void) &Inf_var; \ + \ + x1 = (FLOAT) NaN_var; \ + check (" "#FLOAT" x = ("#FLOAT") ("#DOUBLE") NaN", isnan (x1) != 0); \ + x2 = (FLOAT) Inf_var; \ + check (" "#FLOAT" x = ("#FLOAT") ("#DOUBLE") Inf", isinf (x2) != 0); \ +} + TEST_FUNC (float_test, float, nanf, FLT_EPSILON, HUGE_VALF) TEST_FUNC (double_test, double, nan, DBL_EPSILON, HUGE_VAL) +TEST_TRUNC (truncdfsf_test, float, double) #ifndef NO_LONG_DOUBLE TEST_FUNC (ldouble_test, long double, nanl, LDBL_EPSILON, HUGE_VALL) +TEST_TRUNC (trunctfsf_test, float, long double) +TEST_TRUNC (trunctfdf_test, double, long double) #endif int -main (void) +do_test (void) { float_test (); double_test (); + truncdfsf_test(); #ifndef NO_LONG_DOUBLE ldouble_test (); + trunctfsf_test(); + trunctfdf_test(); #endif return errors != 0; } + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/math/test-misc.c b/math/test-misc.c index d2393cc840..862e11f0c3 100644 --- a/math/test-misc.c +++ b/math/test-misc.c @@ -1,5 +1,5 @@ /* Miscellaneous tests which don't fit anywhere else. - Copyright (C) 2000, 2001, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2004, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -44,7 +44,6 @@ main (void) } } -# if __GNUC__ >= 3 || __GNUC_MINOR__ >= 96 { long double x; long double m; @@ -52,17 +51,17 @@ main (void) int e; int i; -# if LDBL_MANT_DIG == 64 +# if LDBL_MANT_DIG == 64 m = 0xf.fffffffffffffffp-4L; -# elif LDBL_MANT_DIG == 106 +# elif LDBL_MANT_DIG == 106 /* This has to match the mantissa of LDBL_MAX which actually does have a missing bit in the middle. */ m = 0x1.fffffffffffff7ffffffffffff8p-1L; -# elif LDBL_MANT_DIG == 113 +# elif LDBL_MANT_DIG == 113 m = 0x1.ffffffffffffffffffffffffffffp-1L; -# else -# error "Please adjust" -# endif +# else +# error "Please adjust" +# endif for (i = LDBL_MAX_EXP, x = LDBL_MAX; i >= LDBL_MIN_EXP; --i, x /= 2.0L) { @@ -106,9 +105,8 @@ main (void) } } -# endif -#if 0 +# if 0 { int e; long double r = frexpl (LDBL_MIN * LDBL_EPSILON, &e); @@ -126,7 +124,7 @@ main (void) result = 1; } } -#endif +# endif #endif { @@ -1183,5 +1181,59 @@ main (void) } #endif + volatile float f1 = FLT_MAX; + volatile float f2 = FLT_MAX / 2; + (void) &f1; + (void) &f2; + feclearexcept (FE_ALL_EXCEPT); + f2 += f1; + int fe = fetestexcept (FE_ALL_EXCEPT); + if (fe != (FE_OVERFLOW | FE_INEXACT)) + { + printf ("float overflow test failed: %x\n", fe); + result = 1; + } + + volatile double d1 = DBL_MAX; + volatile double d2 = DBL_MAX / 2; + (void) &d1; + (void) &d2; + feclearexcept (FE_ALL_EXCEPT); + d2 += d1; + fe = fetestexcept (FE_ALL_EXCEPT); + if (fe != (FE_OVERFLOW | FE_INEXACT)) + { + printf ("double overflow test failed: %x\n", fe); + result = 1; + } + +#ifndef NO_LONG_DOUBLE + volatile long double ld1 = LDBL_MAX; + volatile long double ld2 = LDBL_MAX / 2; + (void) &ld1; + (void) &ld2; + feclearexcept (FE_ALL_EXCEPT); + ld2 += ld1; + fe = fetestexcept (FE_ALL_EXCEPT); + if (fe != (FE_OVERFLOW | FE_INEXACT)) + { + printf ("long double overflow test failed: %x\n", fe); + result = 1; + } +#endif + +#if !defined NO_LONG_DOUBLE && LDBL_MANT_DIG == 113 + volatile long double ld3 = 0x1.0000000000010000000100000001p+1; + volatile long double ld4 = 0x1.0000000000000000000000000001p+1; + (void) &ld3; + (void) &ld4; + ld3 -= ld4; + if (ld3 != 0x1.0p-47) + { + printf ("long double subtraction test failed %.28La\n", ld3); + result = 1; + } +#endif + return result; } diff --git a/nis/nss_compat/compat-grp.c b/nis/nss_compat/compat-grp.c index f2f7195be1..236c84a20f 100644 --- a/nis/nss_compat/compat-grp.c +++ b/nis/nss_compat/compat-grp.c @@ -580,13 +580,17 @@ internal_getgrgid_r (gid_t gid, struct group *result, ent_t *ent, /* +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/nis/nss_nis/nis-service.c b/nis/nss_nis/nis-service.c index 0c176095c8..59a598f296 100644 --- a/nis/nss_nis/nis-service.c +++ b/nis/nss_nis/nis-service.c @@ -271,7 +271,7 @@ _nss_nis_getservbyname_r (const char *name, const char *protocol, /* 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/nptl/ChangeLog b/nptl/ChangeLog index a237c5e080..425fbf4ba5 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,46 @@ +2007-01-17 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/libc_pthread_init.c: Don't just copy the + function table, mangle the pointers. + * sysdeps/pthread/pthread-functions.h: Define PTHFCT_CALL. + * forward.c: Use PTHFCT_CALL and __libc_pthread_functions_init. + * sysdeps/pthread/bits/libc-lock.h: When using __libc_pthread_functions + demangle pointers before use. + * sysdeps/unix/sysv/linux/s390/jmp-unwind.c: Use PTHFCT_CALL to + demangle pointer. + * sysdeps/unix/sysv/linux/jmp-unwind.c: Likewise. + * sysdeps/pthread/setxid.h: Likewise. + +2007-01-12 Ulrich Drepper <drepper@redhat.com> + + * tst-rwlock7.c: Show some more information in case of correct + behavior. + +2007-01-11 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h + (lll_futex_timed_wait): Undo part of last change, don't negate + return value. + +2007-01-10 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Cleanups. Define + FUTEX_CMP_REQUEUE and lll_futex_requeue. + +2006-12-28 David S. Miller <davem@davemloft.net> + + * shlib-versions: Fix sparc64 linux target specification. + +2007-01-10 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c: + Adjust include path for pthread_barrier_wait.c move. + +2006-12-21 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/pthread_kill.c (pthread_kill): Make sure + tid isn't reread from pd->tid in between ESRCH test and the syscall. + 2006-12-06 Jakub Jelinek <jakub@redhat.com> * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): Handle @@ -66,7 +109,7 @@ * sysdeps/pthread/pthread_getcpuclockid.c: Move to... * pthread_getcpuclockid.c: ...here. - * init.c: USE_TLS support is now default. + * init.c: USE_TLS support is now always enabled. * tst-tls5.h: Likewise. * sysdeps/alpha/tls.h: Likewise. * sysdeps/i386/tls.h: Likewise. diff --git a/nptl/forward.c b/nptl/forward.c index e5f93d475e..b62efd86f8 100644 --- a/nptl/forward.c +++ b/nptl/forward.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -29,16 +29,17 @@ /* Pointers to the libc functions. */ struct pthread_functions __libc_pthread_functions attribute_hidden; +int __libc_pthread_functions_init attribute_hidden; #define FORWARD2(name, rettype, decl, params, defaction) \ rettype \ name decl \ { \ - if (__libc_pthread_functions.ptr_##name == NULL) \ + if (!__libc_pthread_functions_init) \ defaction; \ \ - return __libc_pthread_functions.ptr_##name params; \ + return PTHFCT_CALL (ptr_##name, params); \ } #define FORWARD(name, decl, params, defretval) \ diff --git a/nptl/shlib-versions b/nptl/shlib-versions index 5e18753be2..06ac620f06 100644 --- a/nptl/shlib-versions +++ b/nptl/shlib-versions @@ -1,5 +1,5 @@ mips.*-.*-linux.* libpthread=0 GLIBC_2.0 GLIBC_2.2 -sparc64-.*-linux.* libpthread=0 GLIBC_2.2 +sparc64.*-.*-linux.* libpthread=0 GLIBC_2.2 sh.*-.*-linux.* libpthread=0 GLIBC_2.2 ia64.*-.*-linux.* libpthread=0 GLIBC_2.2 hppa.*-.*-linux.* libpthread=0 GLIBC_2.2 diff --git a/nptl/sysdeps/pthread/bits/libc-lock.h b/nptl/sysdeps/pthread/bits/libc-lock.h index 795caa7135..c4c67ea4d3 100644 --- a/nptl/sysdeps/pthread/bits/libc-lock.h +++ b/nptl/sysdeps/pthread/bits/libc-lock.h @@ -1,5 +1,5 @@ /* libc-internal interface for mutex locks. NPTL version. - Copyright (C) 1996-2001, 2002, 2003, 2005 Free Software Foundation, Inc. + Copyright (C) 1996-2003, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -150,13 +150,17 @@ typedef pthread_key_t __libc_key_t; /* Call thread functions through the function pointer table. */ #if defined SHARED && !defined NOT_IN_libc -# define PTF(NAME) __libc_pthread_functions.ptr_##NAME +# define PTFAVAIL(NAME) __libc_pthread_functions_init # define __libc_ptf_call(FUNC, ARGS, ELSE) \ - (PTF(FUNC) != NULL ? PTF(FUNC) ARGS : ELSE) + (__libc_pthread_functions_init ? PTHFCT_CALL (ptr_##FUNC, ARGS) : ELSE) +# define __libc_ptf_call_always(FUNC, ARGS) \ + PTHFCT_CALL (ptr_##FUNC, ARGS) #else -# define PTF(NAME) NAME +# define PTFAVAIL(NAME) (NAME != NULL) # define __libc_ptf_call(FUNC, ARGS, ELSE) \ __libc_maybe_call (FUNC, ARGS, ELSE) +# define __libc_ptf_call_always(FUNC, ARGS) \ + FUNC ARGS #endif @@ -353,8 +357,9 @@ typedef pthread_key_t __libc_key_t; /* Call handler iff the first call. */ #define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ do { \ - if (PTF(__pthread_once) != NULL) \ - PTF(__pthread_once) (&(ONCE_CONTROL), INIT_FUNCTION); \ + if (PTFAVAIL (__pthread_once)) \ + __libc_ptf_call_always (__pthread_once, (&(ONCE_CONTROL), \ + INIT_FUNCTION)); \ else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \ INIT_FUNCTION (); \ (ONCE_CONTROL) |= 2; \ @@ -380,9 +385,10 @@ extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer { struct _pthread_cleanup_buffer _buffer; \ int _avail; \ if (DOIT) { \ - _avail = PTF(_pthread_cleanup_push_defer) != NULL; \ + _avail = PTFAVAIL (_pthread_cleanup_push_defer); \ if (_avail) { \ - PTF(_pthread_cleanup_push_defer) (&_buffer, FCT, ARG); \ + __libc_ptf_call_always (_pthread_cleanup_push_defer, (&_buffer, FCT, \ + ARG)); \ } else { \ _buffer.__routine = (FCT); \ _buffer.__arg = (ARG); \ @@ -394,7 +400,7 @@ extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer /* End critical region with cleanup. */ #define __libc_cleanup_region_end(DOIT) \ if (_avail) { \ - PTF(_pthread_cleanup_pop_restore) (&_buffer, DOIT); \ + __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\ } else if (DOIT) \ _buffer.__routine (_buffer.__arg); \ } @@ -402,7 +408,7 @@ extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer /* Sometimes we have to exit the block in the middle. */ #define __libc_cleanup_end(DOIT) \ if (_avail) { \ - PTF(_pthread_cleanup_pop_restore) (&_buffer, DOIT); \ + __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\ } else if (DOIT) \ _buffer.__routine (_buffer.__arg) diff --git a/nptl/sysdeps/pthread/pthread-functions.h b/nptl/sysdeps/pthread/pthread-functions.h index 74d24005c3..f8c1e92371 100644 --- a/nptl/sysdeps/pthread/pthread-functions.h +++ b/nptl/sysdeps/pthread/pthread-functions.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. @@ -23,6 +23,7 @@ #include <pthread.h> #include <setjmp.h> #include <internaltypes.h> +#include <sysdep.h> struct xid_command; @@ -100,5 +101,12 @@ struct pthread_functions /* Variable in libc.so. */ extern struct pthread_functions __libc_pthread_functions attribute_hidden; +extern int __libc_pthread_functions_init attribute_hidden; + +#define PTHFCT_CALL(fct, params) \ + ({ __typeof (__libc_pthread_functions.fct) __p; \ + __p = __libc_pthread_functions.fct; \ + PTR_DEMANGLE (__p); \ + __p params; }) #endif /* pthread-functions.h */ diff --git a/nptl/sysdeps/pthread/setxid.h b/nptl/sysdeps/pthread/setxid.h index 8ec382f406..aebdbd236a 100644 --- a/nptl/sysdeps/pthread/setxid.h +++ b/nptl/sysdeps/pthread/setxid.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2004 Free Software Foundation, Inc. +/* Copyright (C) 2004, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -33,13 +33,12 @@ # define INLINE_SETXID_SYSCALL(name, nr, args...) \ ({ \ int __result; \ - if (__builtin_expect (__libc_pthread_functions.ptr__nptl_setxid \ - != NULL, 0)) \ + if (__builtin_expect (__libc_pthread_functions_init, 0)) \ { \ struct xid_command __cmd; \ __cmd.syscall_no = __NR_##name; \ __SETXID_##nr (__cmd, args); \ - __result = __libc_pthread_functions.ptr__nptl_setxid (&__cmd); \ + __result = PTHFCT_CALL (ptr__nptl_setxid, (&__cmd)); \ } \ else \ __result = INLINE_SYSCALL (name, nr, args); \ diff --git a/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c b/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c index c435eff307..f2795510ab 100644 --- a/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c +++ b/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c @@ -1,5 +1,5 @@ /* Clean up stack frames unwound by longjmp. Linux version. - Copyright (C) 1995, 1997, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1995, 1997, 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -29,11 +29,11 @@ void _longjmp_unwind (jmp_buf env, int val) { #ifdef SHARED -# define fptr __libc_pthread_functions.ptr___pthread_cleanup_upto + if (__libc_pthread_functions_init) + PTHFCT_CALL (ptr___pthread_cleanup_upto, (env->__jmpbuf, + CURRENT_STACK_FRAME)); #else -# define fptr __pthread_cleanup_upto + if (__pthread_cleanup_upto != NULL) + __pthread_cleanup_upto (env->__jmpbuf, CURRENT_STACK_FRAME); #endif - - if (fptr != NULL) - fptr (env->__jmpbuf, CURRENT_STACK_FRAME); } diff --git a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c index 714ad49428..92a188a2f3 100644 --- a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c +++ b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -25,6 +25,7 @@ #include <string.h> #include <pthreadP.h> #include <bits/libc-lock.h> +#include <sysdep.h> #ifdef TLS_MULTIPLE_THREADS_IN_TCB @@ -46,11 +47,29 @@ __libc_pthread_init (ptr, reclaim, functions) __register_atfork (NULL, NULL, reclaim, NULL); #ifdef SHARED - /* We copy the content of the variable pointed to by the FUNCTIONS - parameter to one in libc.so since this means access to the array - can be done with one memory access instead of two. */ - memcpy (&__libc_pthread_functions, functions, - sizeof (__libc_pthread_functions)); + /* Copy the function pointers into an array in libc. This enables + access with just one memory reference but moreso, it prevents + hijacking the function pointers with just one pointer change. We + "encrypt" the function pointers since we cannot write-protect the + array easily enough. */ + union ptrhack + { + struct pthread_functions pf; + void *parr[1]; + } const *src; + union ptrhack *dest; +# define NPTRS (sizeof (struct pthread_functions) / sizeof (void *)) + + src = (const void *) functions; + dest = (void *) &__libc_pthread_functions; + + for (size_t cnt = 0; cnt < NPTRS; ++cnt) + { + void *p = src->parr[cnt]; + PTR_MANGLE (p); + dest->parr[cnt] = p; + } + __libc_pthread_functions_init = 1; #endif #ifndef TLS_MULTIPLE_THREADS_IN_TCB @@ -61,7 +80,7 @@ __libc_pthread_init (ptr, reclaim, functions) #ifdef SHARED libc_freeres_fn (freeres_libptread) { - if (__libc_pthread_functions.ptr_freeres != NULL) - __libc_pthread_functions.ptr_freeres (); + if (__libc_pthread_functions_init) + PTHFCT_CALL (ptr_freeres, ()); } #endif diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_kill.c b/nptl/sysdeps/unix/sysv/linux/pthread_kill.c index 9115d6f40b..75089365c3 100644 --- a/nptl/sysdeps/unix/sysv/linux/pthread_kill.c +++ b/nptl/sysdeps/unix/sysv/linux/pthread_kill.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -33,7 +33,15 @@ __pthread_kill (threadid, signo) struct pthread *pd = (struct pthread *) threadid; /* Make sure the descriptor is valid. */ - if (INVALID_TD_P (pd)) + if (DEBUGGING_P && INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Force load of pd->tid into local variable or register. Otherwise + if a thread exits between ESRCH test and tgkill, we might return + EINVAL, because pd->tid would be cleared by the kernel. */ + pid_t tid = atomic_forced_read (pd->tid); + if (__builtin_expect (tid <= 0, 0)) /* Not a valid thread handle. */ return ESRCH; @@ -53,15 +61,15 @@ __pthread_kill (threadid, signo) int val; #if __ASSUME_TGKILL val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), - pd->tid, signo); + tid, signo); #else # ifdef __NR_tgkill val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), - pd->tid, signo); + tid, signo); if (INTERNAL_SYSCALL_ERROR_P (val, err) && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) # endif - val = INTERNAL_SYSCALL (tkill, err, 2, pd->tid, signo); + val = INTERNAL_SYSCALL (tkill, err, 2, tid, signo); #endif return (INTERNAL_SYSCALL_ERROR_P (val, err) diff --git a/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c b/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c index 36886f58a4..3c18df2c4f 100644 --- a/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c +++ b/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c @@ -1,5 +1,5 @@ /* Clean up stack frames unwound by longjmp. Linux/s390 version. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -28,14 +28,13 @@ extern void __pthread_cleanup_upto (__jmp_buf env, char *targetframe); void _longjmp_unwind (jmp_buf env, int val) { + unsigned char local_var; + #ifdef SHARED -# define fptr __libc_pthread_functions.ptr___pthread_cleanup_upto + if (__libc_pthread_functions_init) + PTHFCT_CALL (ptr___pthread_cleanup_upto, (env->__jmpbuf, &local_var)); #else -# define fptr __pthread_cleanup_upto + if (__pthread_cleanup_upto != NULL) + __pthread_cleanup_upto (env->__jmpbuf, &local_var); #endif - - unsigned char local_var; - - if (fptr != NULL) - fptr (env->__jmpbuf, &local_var); } diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c index 7613863bba..55d20eb8f8 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c @@ -1 +1 @@ -#include "../../../../../../pthread/pthread_barrier_wait.c" +#include "../../../../../../../pthread_barrier_wait.c" diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h index 97085bf018..bb988f3b2b 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -35,6 +35,7 @@ #define SYS_futex 202 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_CMP_REQUEUE 4 #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 @@ -150,7 +151,7 @@ LLL_STUB_UNWIND_INFO_END #define lll_futex_wait(futex, val) \ ({ \ int __status; \ - register __typeof (val) _val asm ("edx") = (val); \ + register __typeof (val) _val __asm ("edx") = (val); \ __asm __volatile ("xorq %%r10, %%r10\n\t" \ "syscall" \ : "=a" (__status) \ @@ -163,9 +164,9 @@ LLL_STUB_UNWIND_INFO_END #define lll_futex_timed_wait(futex, val, timeout) \ ({ \ - register const struct timespec *__to __asm__ ("r10") = timeout; \ + register const struct timespec *__to __asm ("r10") = timeout; \ int __status; \ - register __typeof (val) _val asm ("edx") = (val); \ + register __typeof (val) _val __asm ("edx") = (val); \ __asm __volatile ("syscall" \ : "=a" (__status) \ : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAIT), \ @@ -178,7 +179,7 @@ LLL_STUB_UNWIND_INFO_END #define lll_futex_wake(futex, nr) \ do { \ int __ignore; \ - register __typeof (nr) _nr asm ("edx") = (nr); \ + register __typeof (nr) _nr __asm ("edx") = (nr); \ __asm __volatile ("syscall" \ : "=a" (__ignore) \ : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAKE), \ @@ -423,6 +424,21 @@ extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden; : "cx", "r11", "cc", "memory"); }) +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(ftx, nr_wake, nr_move, mutex, val) \ + ({ int __res; \ + register int __nr_move __asm ("r10") = nr_move; \ + register void *__mutex __asm ("r8") = mutex; \ + register int __val __asm ("r9") = val; \ + __asm __volatile ("syscall" \ + : "=a" (__res) \ + : "0" (__NR_futex), "D" ((void *) ftx), \ + "S" (FUTEX_CMP_REQUEUE), "d" (nr_wake), \ + "r" (__nr_move), "r" (__mutex), "r" (__val) \ + : "cx", "r11", "cc", "memory"); \ + __res < 0; }) + + #define lll_mutex_islocked(futex) \ (futex != LLL_MUTEX_LOCK_INITIALIZER) diff --git a/nptl/tst-rwlock7.c b/nptl/tst-rwlock7.c index 1f34c06505..369135b226 100644 --- a/nptl/tst-rwlock7.c +++ b/nptl/tst-rwlock7.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -64,6 +64,7 @@ tf (void *arg) strerror (err), err, strerror (ETIMEDOUT), ETIMEDOUT); pthread_exit ((void *) 1l); } + puts ("child: timedwrlock failed with ETIMEDOUT"); struct timeval tv2; (void) gettimeofday (&tv2, NULL); @@ -93,6 +94,7 @@ tf (void *arg) puts ("2nd timedwrlock did not return EINVAL"); pthread_exit ((void *) 1l); } + puts ("child: timedwrlock failed with EINVAL"); return NULL; } @@ -145,6 +147,7 @@ do_test (void) printf ("round %Zu: rwlock_timedrdlock failed\n", cnt); exit (1); } + printf ("%zu: got timedrdlock\n", cnt); pthread_t th; if (pthread_create (&th, NULL, tf, &r) != 0) diff --git a/nscd/Makefile b/nscd/Makefile index 21657abeb7..ef3ce184f9 100644 --- a/nscd/Makefile +++ b/nscd/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1998,2000,2002,2003,2004,2005,2006 +# Copyright (C) 1998,2000,2002,2003,2004,2005,2006,2007 # Free Software Foundation, Inc. # This file is part of the GNU C Library. @@ -22,7 +22,8 @@ # subdir := nscd -routines := nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai nscd_initgroups +routines := nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \ + nscd_initgroups nscd_getserv_r aux := nscd_helper include ../Makeconfig @@ -32,6 +33,7 @@ vpath %.c ../locale/programs nscd-modules := nscd connections pwdcache getpwnam_r getpwuid_r grpcache \ getgrnam_r getgrgid_r hstcache gethstbyad_r gethstbynm2_r \ + getsrvbynm_r getsrvbypt_r servicescache \ dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \ xmalloc xstrdup aicache initgrcache gai @@ -117,6 +119,9 @@ CFLAGS-aicache.c += $(nscd-cflags) CFLAGS-selinux.c += $(nscd-cflags) CFLAGS-initgrcache.c += $(nscd-cflags) CFLAGS-gai.c += $(nscd-cflags) +CFLAGS-servicescache.c += $(nscd-cflags) +CFLAGS-getsrvbynm_r.c += $(nscd-cflags) +CFLAGS-getsrvbypt_r.c += $(nscd-cflags) ifeq (yesyes,$(have-fpie)$(build-shared)) relro-LDFLAGS += -Wl,-z,now diff --git a/nscd/cache.c b/nscd/cache.c index ef986f374a..73e7902cad 100644 --- a/nscd/cache.c +++ b/nscd/cache.c @@ -1,4 +1,4 @@ -/* Copyright (c) 1998, 1999, 2003-2005, 2006 Free Software Foundation, Inc. +/* Copyright (c) 1998, 1999, 2003-2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -40,6 +40,25 @@ unsigned int reload_count = DEFAULT_RELOAD_LIMIT; +static void (*const readdfcts[LASTREQ]) (struct database_dyn *, + struct hashentry *, + struct datahead *) = +{ + [GETPWBYNAME] = readdpwbyname, + [GETPWBYUID] = readdpwbyuid, + [GETGRBYNAME] = readdgrbyname, + [GETGRBYGID] = readdgrbygid, + [GETHOSTBYNAME] = readdhstbyname, + [GETHOSTBYNAMEv6] = readdhstbynamev6, + [GETHOSTBYADDR] = readdhstbyaddr, + [GETHOSTBYADDRv6] = readdhstbyaddrv6, + [GETAI] = readdhstai, + [INITGROUPS] = readdinitgroups, + [GETSERVBYNAME] = readdservbyname, + [GETSERVBYPORT] = readdservbyport +}; + + /* Search the cache for a matching entry and return it when found. If this fails search the negative cache and return (void *) -1 if this search was successful. Otherwise return NULL. @@ -134,7 +153,10 @@ cache_add (int type, const void *key, size_t len, struct datahead *packet, newp = mempool_alloc (table, sizeof (struct hashentry)); /* If we cannot allocate memory, just do not do anything. */ if (newp == NULL) - return -1; + { + ++table->head->addfailed; + return -1; + } newp->type = type; newp->first = first; @@ -328,51 +350,10 @@ prune_cache (struct database_dyn *table, time_t now, int fd) /* Reload the value. We do this only for the initially used key, not the additionally added derived value. */ - switch (runp->type) - { - case GETPWBYNAME: - readdpwbyname (table, runp, dh); - break; - - case GETPWBYUID: - readdpwbyuid (table, runp, dh); - break; - - case GETGRBYNAME: - readdgrbyname (table, runp, dh); - break; - - case GETGRBYGID: - readdgrbygid (table, runp, dh); - break; - - case GETHOSTBYNAME: - readdhstbyname (table, runp, dh); - break; - - case GETHOSTBYNAMEv6: - readdhstbynamev6 (table, runp, dh); - break; - - case GETHOSTBYADDR: - readdhstbyaddr (table, runp, dh); - break; - - case GETHOSTBYADDRv6: - readdhstbyaddrv6 (table, runp, dh); - break; - - case GETAI: - readdhstai (table, runp, dh); - break; - - case INITGROUPS: - readdinitgroups (table, runp, dh); - break; - - default: - assert (! "should never happen"); - } + assert (runp->type < LASTREQ + && readdfcts[runp->type] != NULL); + + readdfcts[runp->type] (table, runp, dh); /* If the entry has been replaced, we might need cleanup. */ diff --git a/nscd/connections.c b/nscd/connections.c index 3b2558d244..88b44c3034 100644 --- a/nscd/connections.c +++ b/nscd/connections.c @@ -1,5 +1,5 @@ /* Inner loops of cache daemon. - Copyright (C) 1998-2003, 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1998-2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -75,7 +75,7 @@ static void begin_drop_privileges (void); static void finish_drop_privileges (void); /* Map request type to a string. */ -const char *serv2str[LASTREQ] = +const char *const serv2str[LASTREQ] = { [GETPWBYNAME] = "GETPWBYNAME", [GETPWBYUID] = "GETPWBYUID", @@ -92,7 +92,10 @@ const char *serv2str[LASTREQ] = [GETFDGR] = "GETFDGR", [GETFDHST] = "GETFDHST", [GETAI] = "GETAI", - [INITGROUPS] = "INITGROUPS" + [INITGROUPS] = "INITGROUPS", + [GETSERVBYNAME] = "GETSERVBYNAME", + [GETSERVBYPORT] = "GETSERVBYPORT", + [GETFDSERV] = "GETFDSERV" }; /* The control data structures for the services. */ @@ -107,6 +110,7 @@ struct database_dyn dbs[lastdb] = .propagate = 1, .shared = 0, .max_db_size = DEFAULT_MAX_DB_SIZE, + .reset_res = 0, .filename = "/etc/passwd", .db_filename = _PATH_NSCD_PASSWD_DB, .disabled_iov = &pwd_iov_disabled, @@ -125,6 +129,7 @@ struct database_dyn dbs[lastdb] = .propagate = 1, .shared = 0, .max_db_size = DEFAULT_MAX_DB_SIZE, + .reset_res = 0, .filename = "/etc/group", .db_filename = _PATH_NSCD_GROUP_DB, .disabled_iov = &grp_iov_disabled, @@ -143,6 +148,7 @@ struct database_dyn dbs[lastdb] = .propagate = 0, /* Not used. */ .shared = 0, .max_db_size = DEFAULT_MAX_DB_SIZE, + .reset_res = 1, .filename = "/etc/hosts", .db_filename = _PATH_NSCD_HOSTS_DB, .disabled_iov = &hst_iov_disabled, @@ -151,26 +157,55 @@ struct database_dyn dbs[lastdb] = .wr_fd = -1, .ro_fd = -1, .mmap_used = false + }, + [servdb] = { + .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP, + .prunelock = PTHREAD_MUTEX_INITIALIZER, + .enabled = 0, + .check_file = 1, + .persistent = 0, + .propagate = 0, /* Not used. */ + .shared = 0, + .max_db_size = DEFAULT_MAX_DB_SIZE, + .reset_res = 0, + .filename = "/etc/services", + .db_filename = _PATH_NSCD_SERVICES_DB, + .disabled_iov = &serv_iov_disabled, + .postimeout = 28800, + .negtimeout = 20, + .wr_fd = -1, + .ro_fd = -1, + .mmap_used = false } }; /* Mapping of request type to database. */ -static struct database_dyn *const serv2db[LASTREQ] = +static struct { - [GETPWBYNAME] = &dbs[pwddb], - [GETPWBYUID] = &dbs[pwddb], - [GETGRBYNAME] = &dbs[grpdb], - [GETGRBYGID] = &dbs[grpdb], - [GETHOSTBYNAME] = &dbs[hstdb], - [GETHOSTBYNAMEv6] = &dbs[hstdb], - [GETHOSTBYADDR] = &dbs[hstdb], - [GETHOSTBYADDRv6] = &dbs[hstdb], - [GETFDPW] = &dbs[pwddb], - [GETFDGR] = &dbs[grpdb], - [GETFDHST] = &dbs[hstdb], - [GETAI] = &dbs[hstdb], - [INITGROUPS] = &dbs[grpdb] + bool data_request; + struct database_dyn *db; +} const reqinfo[LASTREQ] = +{ + [GETPWBYNAME] = { true, &dbs[pwddb] }, + [GETPWBYUID] = { true, &dbs[pwddb] }, + [GETGRBYNAME] = { true, &dbs[grpdb] }, + [GETGRBYGID] = { true, &dbs[grpdb] }, + [GETHOSTBYNAME] = { true, &dbs[hstdb] }, + [GETHOSTBYNAMEv6] = { true, &dbs[hstdb] }, + [GETHOSTBYADDR] = { true, &dbs[hstdb] }, + [GETHOSTBYADDRv6] = { true, &dbs[hstdb] }, + [SHUTDOWN] = { false, NULL }, + [GETSTAT] = { false, NULL }, + [SHUTDOWN] = { false, NULL }, + [GETFDPW] = { false, &dbs[pwddb] }, + [GETFDGR] = { false, &dbs[grpdb] }, + [GETFDHST] = { false, &dbs[hstdb] }, + [GETAI] = { true, &dbs[hstdb] }, + [INITGROUPS] = { true, &dbs[grpdb] }, + [GETSERVBYNAME] = { true, &dbs[servdb] }, + [GETSERVBYPORT] = { true, &dbs[servdb] }, + [GETFDSERV] = { false, &dbs[servdb] } }; @@ -305,7 +340,7 @@ check_use (const char *data, nscd_ssize_t first_free, uint8_t *usemap, static int verify_persistent_db (void *mem, struct database_pers_head *readhead, int dbnr) { - assert (dbnr == pwddb || dbnr == grpdb || dbnr == hstdb); + assert (dbnr == pwddb || dbnr == grpdb || dbnr == hstdb || dbnr == servdb); time_t now = time (NULL); @@ -357,7 +392,7 @@ verify_persistent_db (void *mem, struct database_pers_head *readhead, int dbnr) /* Make sure the record is for this type of service. */ if (here->type >= LASTREQ - || serv2db[here->type] != &dbs[dbnr]) + || reqinfo[here->type].db != &dbs[dbnr]) goto fail; /* Validate boolean field value. */ @@ -821,18 +856,16 @@ invalidate_cache (char *key, int fd) dbtype number; int32_t resp; - if (strcmp (key, "passwd") == 0) - number = pwddb; - else if (strcmp (key, "group") == 0) - number = grpdb; - else if (__builtin_expect (strcmp (key, "hosts"), 0) == 0) - { - number = hstdb; + for (number = pwddb; number < lastdb; ++number) + if (strcmp (key, dbnames[number]) == 0) + { + if (dbs[number].reset_res) + res_init (); - /* Re-initialize the resolver. resolv.conf might have changed. */ - res_init (); - } - else + break; + } + + if (number == lastdb) { resp = EINVAL; writeall (fd, &resp, sizeof (resp)); @@ -907,22 +940,14 @@ cannot handle old request version %d; current version is %d"), return; } - /* Make the SELinux check before we go on to the standard checks. We - need to verify that the request type is valid, since it has not - yet been checked at this point. */ - if (selinux_enabled - && __builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME - && __builtin_expect (req->type, LASTREQ) < LASTREQ - && nscd_request_avc_has_perm (fd, req->type) != 0) + /* Make the SELinux check before we go on to the standard checks. */ + if (selinux_enabled && nscd_request_avc_has_perm (fd, req->type) != 0) return; - struct database_dyn *db = serv2db[req->type]; + struct database_dyn *db = reqinfo[req->type].db; - // XXX Clean up so that each new command need not introduce a - // XXX new conditional. - if ((__builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME - && __builtin_expect (req->type, LASTDBREQ) <= LASTDBREQ) - || req->type == GETAI || req->type == INITGROUPS) + /* See whether we can service the request from the cache. */ + if (__builtin_expect (reqinfo[req->type].data_request, true)) { if (__builtin_expect (debug_level, 0) > 0) { @@ -940,7 +965,7 @@ cannot handle old request version %d; current version is %d"), } /* Is this service enabled? */ - if (!db->enabled) + if (__builtin_expect (!db->enabled, 0)) { /* No, sent the prepared record. */ if (TEMP_FAILURE_RETRY (send (fd, db->disabled_iov->iov_base, @@ -1066,6 +1091,14 @@ cannot handle old request version %d; current version is %d"), addinitgroups (db, fd, req, key, uid); break; + case GETSERVBYNAME: + addservbyname (db, fd, req, key, uid); + break; + + case GETSERVBYPORT: + addservbyport (db, fd, req, key, uid); + break; + case GETSTAT: case SHUTDOWN: case INVALIDATE: @@ -1111,8 +1144,9 @@ cannot handle old request version %d; current version is %d"), case GETFDPW: case GETFDGR: case GETFDHST: + case GETFDSERV: #ifdef SCM_RIGHTS - send_ro_fd (serv2db[req->type], key, fd); + send_ro_fd (reqinfo[req->type].db, key, fd); #endif break; @@ -1152,7 +1186,7 @@ cannot open /proc/self/cmdline: %s; disabling paranoia mode"), if (n == -1) { dbg_log (_("\ -cannot open /proc/self/cmdline: %s; disabling paranoia mode"), +cannot read /proc/self/cmdline: %s; disabling paranoia mode"), strerror (errno)); close (fd); diff --git a/nscd/gai.c b/nscd/gai.c index 2e706bdfe7..46f8b8bec9 100644 --- a/nscd/gai.c +++ b/nscd/gai.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 2004. @@ -17,7 +17,6 @@ /* 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 #define __inet_aton inet_aton #define __getsockname getsockname #define __socket socket diff --git a/nscd/getsrvbynm_r.c b/nscd/getsrvbynm_r.c new file mode 100644 index 0000000000..fb60f4802d --- /dev/null +++ b/nscd/getsrvbynm_r.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1996, 1997, 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <netdb.h> + + +#define LOOKUP_TYPE struct servent +#define FUNCTION_NAME getservbyname +#define DATABASE_NAME services +#define ADD_PARAMS const char *name, const char *proto +#define ADD_VARIABLES name, proto + +#include "../nss/getXXbyYY_r.c" diff --git a/nscd/getsrvbypt_r.c b/nscd/getsrvbypt_r.c new file mode 100644 index 0000000000..fd5b11bc3d --- /dev/null +++ b/nscd/getsrvbypt_r.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1996, 1997, 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <netdb.h> + + +#define LOOKUP_TYPE struct servent +#define FUNCTION_NAME getservbyport +#define DATABASE_NAME services +#define ADD_PARAMS int port, const char *proto +#define ADD_VARIABLES port, proto + +#include "../nss/getXXbyYY_r.c" diff --git a/nscd/grpcache.c b/nscd/grpcache.c index 5a8fba4759..54d1ef1eef 100644 --- a/nscd/grpcache.c +++ b/nscd/grpcache.c @@ -1,5 +1,5 @@ /* Cache handling for group lookup. - Copyright (C) 1998-2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -445,23 +445,14 @@ addgrbyX (struct database_dyn *db, int fd, request_header *req, dbg_log (_("Reloading \"%s\" in group cache!"), keystr); } -#if 0 - uid_t oldeuid = 0; - if (db->secure) - { - oldeuid = geteuid (); - pthread_seteuid_np (uid); - } -#endif - while (lookup (req->type, key, &resultbuf, buffer, buflen, &grp) != 0 && (errval = errno) == ERANGE) { - char *old_buffer = buffer; errno = 0; if (__builtin_expect (buflen > 32768, 0)) { + char *old_buffer = buffer; buflen *= 2; buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen); if (buffer == NULL) @@ -486,11 +477,6 @@ addgrbyX (struct database_dyn *db, int fd, request_header *req, buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen); } -#if 0 - if (db->secure) - pthread_seteuid_np (oldeuid); -#endif - cache_addgr (db, fd, req, keystr, grp, uid, he, dh, errval); if (use_malloc) diff --git a/nscd/hstcache.c b/nscd/hstcache.c index e27ece5bc6..742491aea3 100644 --- a/nscd/hstcache.c +++ b/nscd/hstcache.c @@ -1,5 +1,5 @@ /* Cache handling for host lookup. - Copyright (C) 1998-2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -463,24 +463,15 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req, dbg_log (_("Reloading \"%s\" in hosts cache!"), (char *) str); } -#if 0 - uid_t oldeuid = 0; - if (db->secure) - { - oldeuid = geteuid (); - pthread_seteuid_np (uid); - } -#endif - while (lookup (req->type, key, &resultbuf, buffer, buflen, &hst) != 0 && h_errno == NETDB_INTERNAL && (errval = errno) == ERANGE) { - char *old_buffer = buffer; errno = 0; if (__builtin_expect (buflen > 32768, 0)) { + char *old_buffer = buffer; buflen *= 2; buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen); if (buffer == NULL) @@ -505,11 +496,6 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req, buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen); } -#if 0 - if (db->secure) - pthread_seteuid_np (oldeuid); -#endif - cache_addhst (db, fd, req, key, hst, uid, he, dh, h_errno == TRY_AGAIN ? errval : 0); diff --git a/nscd/nscd-client.h b/nscd/nscd-client.h index 0fd2d9f547..7702f590bd 100644 --- a/nscd/nscd-client.h +++ b/nscd/nscd-client.h @@ -1,4 +1,4 @@ -/* Copyright (c) 1998, 1999, 2000, 2003, 2004, 2005, 2006 +/* Copyright (c) 1998, 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. @@ -56,7 +56,6 @@ typedef enum GETHOSTBYNAMEv6, GETHOSTBYADDR, GETHOSTBYADDRv6, - LASTDBREQ = GETHOSTBYADDRv6, SHUTDOWN, /* Shut the server down. */ GETSTAT, /* Get the server statistic. */ INVALIDATE, /* Invalidate one special cache. */ @@ -65,6 +64,9 @@ typedef enum GETFDHST, GETAI, INITGROUPS, + GETSERVBYNAME, + GETSERVBYPORT, + GETFDSERV, LASTREQ } request_type; @@ -153,6 +155,19 @@ typedef struct } initgr_response_header; +/* Structure sent in reply to services query. Note that this struct is + sent also if the service is disabled or there is no record found. */ +typedef struct +{ + int32_t version; + int32_t found; + nscd_ssize_t s_name_len; + nscd_ssize_t s_proto_len; + nscd_ssize_t s_aliases_cnt; + int32_t s_port; +} serv_response_header; + + /* Type for offsets in data part of database. */ typedef uint32_t ref_t; /* Value for invalid/no reference. */ @@ -186,6 +201,7 @@ struct datahead hst_response_header hstdata; ai_response_header aidata; initgr_response_header initgrdata; + serv_response_header servdata; nscd_ssize_t align1; nscd_time_t align2; } data[0]; diff --git a/nscd/nscd.c b/nscd/nscd.c index 588b09d4fb..1ae419be49 100644 --- a/nscd/nscd.c +++ b/nscd/nscd.c @@ -1,4 +1,4 @@ -/* Copyright (c) 1998-2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (c) 1998-2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. @@ -336,15 +336,15 @@ parse_opt (int key, char *arg, struct argp_state *state) exit (EXIT_FAILURE); request_header req; - if (strcmp (arg, "passwd") == 0) - req.key_len = sizeof "passwd"; - else if (strcmp (arg, "group") == 0) - req.key_len = sizeof "group"; - else if (strcmp (arg, "hosts") == 0) - req.key_len = sizeof "hosts"; - else + dbtype cnt; + for (cnt = pwddb; cnt < lastdb; ++cnt) + if (strcmp (arg, dbnames[cnt]) == 0) + break; + + if (cnt == lastdb) return ARGP_ERR_UNKNOWN; + req.key_len = strlen (arg) + 1; req.version = NSCD_VERSION; req.type = INVALIDATE; @@ -406,7 +406,7 @@ print_version (FILE *stream, struct argp_state *state) Copyright (C) %s Free Software Foundation, Inc.\n\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ -"), "2006"); +"), "2007"); fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk and Ulrich Drepper"); } diff --git a/nscd/nscd.conf b/nscd/nscd.conf index 954eafd554..b0762fbb53 100644 --- a/nscd/nscd.conf +++ b/nscd/nscd.conf @@ -26,7 +26,7 @@ # max-db-size <service> <number bytes> # auto-propagate <service> <yes|no> # -# Currently supported cache names (services): passwd, group, hosts +# Currently supported cache names (services): passwd, group, hosts, services # @@ -68,3 +68,12 @@ persistent hosts yes shared hosts yes max-db-size hosts 33554432 + + enable-cache services yes + positive-time-to-live services 28800 + negative-time-to-live services 20 + suggested-size services 211 + check-files services yes + persistent services yes + shared services yes + max-db-size services 33554432 diff --git a/nscd/nscd.h b/nscd/nscd.h index 5c2ff3a95b..e8199b8009 100644 --- a/nscd/nscd.h +++ b/nscd/nscd.h @@ -1,4 +1,4 @@ -/* Copyright (c) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 +/* Copyright (c) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. @@ -38,6 +38,7 @@ typedef enum pwddb, grpdb, hstdb, + servdb, lastdb } dbtype; @@ -65,7 +66,8 @@ struct database_dyn int persistent; int shared; int propagate; - const char filename[12]; + int reset_res; + const char filename[16]; const char *db_filename; time_t file_mtime; size_t suggested_module; @@ -92,6 +94,7 @@ struct database_dyn #define _PATH_NSCD_PASSWD_DB "/var/db/nscd/passwd" #define _PATH_NSCD_GROUP_DB "/var/db/nscd/group" #define _PATH_NSCD_HOSTS_DB "/var/db/nscd/hosts" +#define _PATH_NSCD_SERVICES_DB "/var/db/nscd/services" /* Path used when not using persistent storage. */ #define _PATH_NSCD_XYZ_DB_TMP "/var/run/nscd/dbXXXXXX" @@ -110,12 +113,13 @@ struct database_dyn /* Global variables. */ extern struct database_dyn dbs[lastdb]; -extern const char *dbnames[lastdb]; -extern const char *serv2str[LASTREQ]; +extern const char *const dbnames[lastdb]; +extern const char *const serv2str[LASTREQ]; extern const struct iovec pwd_iov_disabled; extern const struct iovec grp_iov_disabled; extern const struct iovec hst_iov_disabled; +extern const struct iovec serv_iov_disabled; /* Initial number of threads to run. */ @@ -238,6 +242,16 @@ extern void addinitgroups (struct database_dyn *db, int fd, extern void readdinitgroups (struct database_dyn *db, struct hashentry *he, struct datahead *dh); +/* servicecache.c */ +extern void addservbyname (struct database_dyn *db, int fd, + request_header *req, void *key, uid_t uid); +extern void readdservbyname (struct database_dyn *db, struct hashentry *he, + struct datahead *dh); +extern void addservbyport (struct database_dyn *db, int fd, + request_header *req, void *key, uid_t uid); +extern void readdservbyport (struct database_dyn *db, struct hashentry *he, + struct datahead *dh); + /* mem.c */ extern void *mempool_alloc (struct database_dyn *db, size_t len); extern void gc (struct database_dyn *db); diff --git a/nscd/nscd_conf.c b/nscd/nscd_conf.c index 2048eca886..e724c6bd59 100644 --- a/nscd/nscd_conf.c +++ b/nscd/nscd_conf.c @@ -1,4 +1,4 @@ -/* Copyright (c) 1998,2000,2003,2004,2005,2006 Free Software Foundation, Inc. +/* Copyright (c) 1998, 2000, 2003-2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. @@ -37,11 +37,12 @@ extern char *xstrdup (const char *s); /* Names of the databases. */ -const char *dbnames[lastdb] = +const char *const dbnames[lastdb] = { [pwddb] = "passwd", [grpdb] = "group", - [hstdb] = "hosts" + [hstdb] = "hosts", + [servdb] = "services" }; @@ -52,7 +53,7 @@ find_db (const char *name) if (strcmp (name, dbnames[cnt]) == 0) return cnt; - error (0, 0, _("database %s is not supported\n"), name); + error (0, 0, _("database %s is not supported"), name); return -1; } diff --git a/nscd/nscd_gethst_r.c b/nscd/nscd_gethst_r.c index 516977bcc4..e83e4823ea 100644 --- a/nscd/nscd_gethst_r.c +++ b/nscd/nscd_gethst_r.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998-2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -17,15 +17,10 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include <assert.h> #include <errno.h> -#include <netdb.h> #include <resolv.h> -#include <stdint.h> #include <stdio.h> -#include <stdlib.h> #include <string.h> -#include <unistd.h> #include <arpa/nameser.h> #include <not-cancel.h> @@ -175,7 +170,7 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, if (sock == -1) { __nss_not_use_nscd_hosts = 1; - goto out;; + goto out; } hst_resp = &hst_resp_mem; @@ -193,7 +188,6 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, if (hst_resp->found == 1) { - struct iovec vec[4]; char *cp = buffer; uintptr_t align1; uintptr_t align2; @@ -253,6 +247,8 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, if (h_name == NULL) { + struct iovec vec[4]; + vec[0].iov_base = resultbuf->h_name; vec[0].iov_len = hst_resp->h_name_len; total_len = hst_resp->h_name_len; diff --git a/nscd/nscd_getserv_r.c b/nscd/nscd_getserv_r.c new file mode 100644 index 0000000000..ea5dcedb88 --- /dev/null +++ b/nscd/nscd_getserv_r.c @@ -0,0 +1,306 @@ +/* Copyright (C) 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2007. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <string.h> +#include <not-cancel.h> +#include <stdio-common/_itoa.h> + +#include "nscd-client.h" +#include "nscd_proto.h" + + +int __nss_not_use_nscd_services; + + +static int nscd_getserv_r (const char *crit, size_t critlen, const char *proto, + request_type type, struct servent *resultbuf, + char *buf, size_t buflen, struct servent **result); + + +int +__nscd_getservbyname_r (const char *name, const char *proto, + struct servent *result_buf, char *buf, size_t buflen, + struct servent **result) +{ + return nscd_getserv_r (name, strlen (name), proto, GETSERVBYNAME, result_buf, + buf, buflen, result); +} + + +int +__nscd_getservbyport_r (int port, const char *proto, + struct servent *result_buf, char *buf, size_t buflen, + struct servent **result) +{ + char portstr[3 * sizeof (int) + 2]; + portstr[sizeof (portstr) - 1] = '\0'; + char *cp = _itoa_word (port, portstr + sizeof (portstr) - 1, 10, 0); + + return nscd_getserv_r (portstr, portstr + sizeof (portstr) - cp, proto, + GETSERVBYPORT, result_buf, buf, buflen, result); +} + + +libc_locked_map_ptr (, __serv_map_handle) attribute_hidden; +/* Note that we only free the structure if necessary. The memory + mapping is not removed since it is not visible to the malloc + handling. */ +libc_freeres_fn (serv_map_free) +{ + if (__serv_map_handle.mapped != NO_MAPPING) + { + void *p = __serv_map_handle.mapped; + __serv_map_handle.mapped = NO_MAPPING; + free (p); + } +} + + +static int +nscd_getserv_r (const char *crit, size_t critlen, const char *proto, + request_type type, struct servent *resultbuf, + char *buf, size_t buflen, struct servent **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 (GETFDSERV, "services", &__serv_map_handle, + &gc_cycle); + size_t protolen = proto == NULL ? 0 : strlen (proto); + size_t keylen = critlen + 1 + protolen + 1; + char *key = alloca (keylen); + memcpy (__mempcpy (__mempcpy (key, crit, critlen), + "/", 1), proto ?: "", protolen + 1); + + retry:; + const serv_response_header *serv_resp = NULL; + const char *s_name = NULL; + const char *s_proto = NULL; + const uint32_t *aliases_len = NULL; + const char *aliases_list = NULL; + int retval = -1; + const char *recend = (const char *) ~UINTMAX_C (0); + int sock = -1; + if (mapped != NO_MAPPING) + { + const struct datahead *found = __nscd_cache_search (type, key, keylen, + mapped); + + if (found != NULL) + { + serv_resp = &found->data[0].servdata; + s_name = (char *) (serv_resp + 1); + s_proto = s_name + serv_resp->s_name_len; + aliases_len = (uint32_t *) (s_proto + serv_resp->s_proto_len); + aliases_list = ((char *) aliases_len + + serv_resp->s_aliases_cnt * sizeof (uint32_t)); + +#ifndef _STRING_ARCH_unaligned + /* The aliases_len array in the mapped database might very + well be unaligned. We will access it word-wise so on + platforms which do not tolerate unaligned accesses we + need to make an aligned copy. */ + if (((uintptr_t) aliases_len & (__alignof__ (*aliases_len) - 1)) + != 0) + { + uint32_t *tmp = alloca (hst_resp->h_aliases_cnt + * sizeof (uint32_t)); + aliases_len = memcpy (tmp, aliases_len, + hst_resp->h_aliases_cnt + * sizeof (uint32_t)); + } +#endif + recend = (const char *) found->data + found->recsize; + if (__builtin_expect ((const char *) aliases_len + + serv_resp->s_aliases_cnt * sizeof (uint32_t) + > recend, 0)) + goto out_close; + } + } + + serv_response_header serv_resp_mem; + if (serv_resp == NULL) + { + sock = __nscd_open_socket (key, keylen, type, &serv_resp_mem, + sizeof (serv_resp_mem)); + if (sock == -1) + { + __nss_not_use_nscd_services = 1; + goto out; + } + + serv_resp = &serv_resp_mem; + } + + /* No value found so far. */ + *result = NULL; + + if (__builtin_expect (serv_resp->found == -1, 0)) + { + /* The daemon does not cache this database. */ + __nss_not_use_nscd_services = 1; + goto out_close; + } + + if (serv_resp->found == 1) + { + char *cp = buf; + uintptr_t align1; + uintptr_t align2; + size_t total_len; + ssize_t cnt; + int n; + + /* A first check whether the buffer is sufficiently large is possible. */ + /* Now allocate the buffer the array for the group members. We must + align the pointer and the base of the h_addr_list pointers. */ + align1 = ((__alignof__ (char *) - (cp - ((char *) 0))) + & (__alignof__ (char *) - 1)); + align2 = ((__alignof__ (char *) - ((cp + align1 + serv_resp->s_name_len + + serv_resp->s_proto_len) + - ((char *) 0))) + & (__alignof__ (char *) - 1)); + if (buflen < (align1 + serv_resp->s_name_len + serv_resp->s_proto_len + + align2 + + (serv_resp->s_aliases_cnt + 1) * sizeof (char *))) + { + no_room: + __set_errno (ERANGE); + retval = ERANGE; + goto out_close; + } + cp += align1; + + /* Prepare the result as far as we can. */ + resultbuf->s_aliases = (char **) cp; + cp += (serv_resp->s_aliases_cnt + 1) * sizeof (char *); + + resultbuf->s_name = cp; + cp += serv_resp->s_name_len; + resultbuf->s_proto = cp; + cp += serv_resp->s_proto_len + align2; + resultbuf->s_port = serv_resp->s_port; + + if (s_name == NULL) + { + struct iovec vec[2]; + + vec[0].iov_base = resultbuf->s_name; + vec[0].iov_len = serv_resp->s_name_len + serv_resp->s_proto_len; + total_len = vec[0].iov_len; + n = 1; + + if (serv_resp->s_aliases_cnt > 0) + { + aliases_len = alloca (serv_resp->s_aliases_cnt + * sizeof (uint32_t)); + vec[n].iov_base = (void *) aliases_len; + vec[n].iov_len = serv_resp->s_aliases_cnt * sizeof (uint32_t); + + total_len += serv_resp->s_aliases_cnt * sizeof (uint32_t); + ++n; + } + + if ((size_t) __readvall (sock, vec, n) != total_len) + goto out_close; + } + else + memcpy (resultbuf->s_name, s_name, + serv_resp->s_name_len + serv_resp->s_proto_len); + + /* Now we also can read the aliases. */ + total_len = 0; + for (cnt = 0; cnt < serv_resp->s_aliases_cnt; ++cnt) + { + resultbuf->s_aliases[cnt] = cp; + cp += aliases_len[cnt]; + total_len += aliases_len[cnt]; + } + resultbuf->s_aliases[cnt] = NULL; + + if (__builtin_expect ((const char *) aliases_list + total_len > recend, + 0)) + goto out_close; + /* See whether this would exceed the buffer capacity. */ + if (__builtin_expect (cp > buf + buflen, 0)) + goto no_room; + + /* And finally read the aliases. */ + if (aliases_list == NULL) + { + if (total_len == 0 + || ((size_t) __readall (sock, resultbuf->s_aliases[0], total_len) + == total_len)) + { + retval = 0; + *result = resultbuf; + } + } + else + { + memcpy (resultbuf->s_aliases[0], aliases_list, total_len); + + /* Try to detect corrupt databases. */ + if (resultbuf->s_name[serv_resp->s_name_len - 1] != '\0' + || resultbuf->s_proto[serv_resp->s_proto_len - 1] != '\0' + || ({for (cnt = 0; cnt < serv_resp->s_aliases_cnt; ++cnt) + if (resultbuf->s_aliases[cnt][aliases_len[cnt] - 1] + != '\0') + break; + cnt < serv_resp->s_aliases_cnt; })) + /* We cannot use the database. */ + goto out_close; + + retval = 0; + *result = resultbuf; + } + } + else + { + /* The `errno' to some value != ERANGE. */ + __set_errno (ENOENT); + /* Even though we have not found anything, the result is zero. */ + retval = 0; + } + + out_close: + if (sock != -1) + close_not_cancel_no_status (sock); + out: + if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1) + { + /* 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) + { + /* nscd is just running gc now. Disable using the mapping. */ + __nscd_unmap (mapped); + mapped = NO_MAPPING; + } + + goto retry; + } + + return retval; +} diff --git a/nscd/nscd_proto.h b/nscd/nscd_proto.h index 64d9bd0043..573ca2b2e7 100644 --- a/nscd/nscd_proto.h +++ b/nscd/nscd_proto.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 1999, 2000, 2002, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1998-2000, 2002, 2004, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. @@ -35,6 +35,7 @@ struct nscd_ai_result; extern int __nss_not_use_nscd_passwd attribute_hidden; extern int __nss_not_use_nscd_group attribute_hidden; extern int __nss_not_use_nscd_hosts attribute_hidden; +extern int __nss_not_use_nscd_services attribute_hidden; extern int __nscd_getpwnam_r (const char *name, struct passwd *resultbuf, char *buffer, size_t buflen, @@ -64,4 +65,11 @@ extern int __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop); extern int __nscd_getgrouplist (const char *user, gid_t group, long int *size, gid_t **groupsp, long int limit); +extern int __nscd_getservbyname_r (const char *name, const char *proto, + struct servent *result_buf, char *buf, + size_t buflen, struct servent **result); +extern int __nscd_getservbyport_r (int port, const char *proto, + struct servent *result_buf, char *buf, + size_t buflen, struct servent **result); + #endif /* _NSCD_PROTO_H */ diff --git a/nscd/pwdcache.c b/nscd/pwdcache.c index 01c223add5..0461ec91ce 100644 --- a/nscd/pwdcache.c +++ b/nscd/pwdcache.c @@ -1,5 +1,5 @@ /* Cache handling for passwd lookup. - Copyright (C) 1998-2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -440,23 +440,14 @@ addpwbyX (struct database_dyn *db, int fd, request_header *req, dbg_log (_("Reloading \"%s\" in password cache!"), keystr); } -#if 0 - uid_t oldeuid = 0; - if (db->secure) - { - oldeuid = geteuid (); - pthread_seteuid_np (c_uid); - } -#endif - while (lookup (req->type, key, &resultbuf, buffer, buflen, &pwd) != 0 && (errval = errno) == ERANGE) { - char *old_buffer = buffer; errno = 0; if (__builtin_expect (buflen > 32768, 0)) { + char *old_buffer = buffer; buflen *= 2; buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen); if (buffer == NULL) @@ -481,11 +472,6 @@ addpwbyX (struct database_dyn *db, int fd, request_header *req, buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen); } -#if 0 - if (db->secure) - pthread_seteuid_np (oldeuid); -#endif - /* Add the entry to the cache. */ cache_addpw (db, fd, req, keystr, pwd, c_uid, he, dh, errval); diff --git a/nscd/selinux.c b/nscd/selinux.c index f0620d1012..4a462223f5 100644 --- a/nscd/selinux.c +++ b/nscd/selinux.c @@ -1,5 +1,5 @@ /* SELinux access controls for nscd. - Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Matthew Rickard <mjricka@epoch.ncsc.mil>, 2004. @@ -63,7 +63,12 @@ static const int perms[LASTREQ] = [GETFDGR] = NSCD__SHMEMGRP, [GETFDHST] = NSCD__SHMEMHOST, [GETAI] = NSCD__GETHOST, - [INITGROUPS] = NSCD__GETGRP + [INITGROUPS] = NSCD__GETGRP, +#ifdef NSCD__GETSERV + [GETSERVBYNAME] = NSCD__GETSERV, + [GETSERVBYPORT] = NSCD__GETSERV, + [GETFDSERV] = NSCD__SHMEMSERV, +#endif }; /* Store an entry ref to speed AVC decisions. */ diff --git a/nscd/servicescache.c b/nscd/servicescache.c new file mode 100644 index 0000000000..ea4fa35100 --- /dev/null +++ b/nscd/servicescache.c @@ -0,0 +1,473 @@ +/* Cache handling for services lookup. + Copyright (C) 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@drepper.com>, 2007. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <alloca.h> +#include <assert.h> +#include <errno.h> +#include <libintl.h> +#include <netdb.h> +#include <unistd.h> +#include <sys/mman.h> + +#include "nscd.h" +#include "dbg_log.h" + + +/* This is the standard reply in case the service is disabled. */ +static const serv_response_header disabled = +{ + .version = NSCD_VERSION, + .found = -1, + .s_name_len = 0, + .s_proto_len = 0, + .s_aliases_cnt = 0, + .s_port = -1 +}; + +/* This is the struct describing how to write this record. */ +const struct iovec serv_iov_disabled = +{ + .iov_base = (void *) &disabled, + .iov_len = sizeof (disabled) +}; + + +/* This is the standard reply in case we haven't found the dataset. */ +static const serv_response_header notfound = +{ + .version = NSCD_VERSION, + .found = 0, + .s_name_len = 0, + .s_proto_len = 0, + .s_aliases_cnt = 0, + .s_port = -1 +}; + + +static void +cache_addserv (struct database_dyn *db, int fd, request_header *req, + const void *key, struct servent *serv, uid_t owner, + struct hashentry *he, struct datahead *dh, int errval) +{ + ssize_t total; + ssize_t written; + time_t t = time (NULL); + + /* We allocate all data in one memory block: the iov vector, + the response header and the dataset itself. */ + struct dataset + { + struct datahead head; + serv_response_header resp; + char strdata[0]; + } *dataset; + + assert (offsetof (struct dataset, resp) == offsetof (struct datahead, data)); + + if (serv == NULL) + { + if (he != NULL && errval == EAGAIN) + { + /* If we have an old record available but cannot find one + now because the service is not available we keep the old + record and make sure it does not get removed. */ + if (reload_count != UINT_MAX) + /* Do not reset the value if we never not reload the record. */ + dh->nreloads = reload_count - 1; + + written = total = 0; + } + else + { + /* We have no data. This means we send the standard reply for this + case. */ + total = sizeof (notfound); + + 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. */ + if (dataset != NULL) + { + dataset->head.allocsize = sizeof (struct dataset) + req->key_len; + dataset->head.recsize = total; + dataset->head.notfound = true; + dataset->head.nreloads = 0; + dataset->head.usable = true; + + /* Compute the timeout time. */ + dataset->head.timeout = t + db->negtimeout; + + /* This is the reply. */ + memcpy (&dataset->resp, ¬found, total); + + /* Copy the key data. */ + memcpy (dataset->strdata, key, req->key_len); + + /* If necessary, we also propagate the data to disk. */ + if (db->persistent) + { + // XXX async OK? + uintptr_t pval = (uintptr_t) dataset & ~pagesize_m1; + msync ((void *) pval, + ((uintptr_t) dataset & pagesize_m1) + + sizeof (struct dataset) + req->key_len, MS_ASYNC); + } + + /* Now get the lock to safely insert the records. */ + pthread_rwlock_rdlock (&db->lock); + + if (cache_add (req->type, &dataset->strdata, req->key_len, + &dataset->head, true, db, owner) < 0) + /* Ensure the data can be recovered. */ + dataset->head.usable = false; + + pthread_rwlock_unlock (&db->lock); + + /* Mark the old entry as obsolete. */ + if (dh != NULL) + dh->usable = false; + } + else + ++db->head->addfailed; + } + } + else + { + /* Determine the I/O structure. */ + size_t s_name_len = strlen (serv->s_name) + 1; + size_t s_proto_len = strlen (serv->s_proto) + 1; + uint32_t *s_aliases_len; + size_t s_aliases_cnt; + char *aliases; + char *cp; + size_t cnt; + + /* Determine the number of aliases. */ + s_aliases_cnt = 0; + for (cnt = 0; serv->s_aliases[cnt] != NULL; ++cnt) + ++s_aliases_cnt; + /* Determine the length of all aliases. */ + s_aliases_len = (uint32_t *) alloca (s_aliases_cnt * sizeof (uint32_t)); + total = 0; + for (cnt = 0; cnt < s_aliases_cnt; ++cnt) + { + s_aliases_len[cnt] = strlen (serv->s_aliases[cnt]) + 1; + total += s_aliases_len[cnt]; + } + + total += (sizeof (struct dataset) + + s_name_len + + s_proto_len + + s_aliases_cnt * sizeof (uint32_t)); + written = total; + + /* If we refill the cache, first assume the reconrd did not + change. Allocate memory on the cache since it is likely + discarded anyway. If it turns out to be necessary to have a + new record we can still allocate real memory. */ + bool alloca_used = false; + dataset = NULL; + + if (he == NULL) + { + dataset = (struct dataset *) mempool_alloc (db, + total + req->key_len); + if (dataset == NULL) + ++db->head->addfailed; + } + + if (dataset == NULL) + { + /* We cannot permanently add the result in the moment. But + we can provide the result as is. Store the data in some + temporary memory. */ + dataset = (struct dataset *) alloca (total + req->key_len); + + /* We cannot add this record to the permanent database. */ + alloca_used = true; + } + + dataset->head.allocsize = total + req->key_len; + dataset->head.recsize = total - offsetof (struct dataset, resp); + dataset->head.notfound = false; + dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); + dataset->head.usable = true; + + /* Compute the timeout time. */ + dataset->head.timeout = t + db->postimeout; + + dataset->resp.version = NSCD_VERSION; + dataset->resp.found = 1; + dataset->resp.s_name_len = s_name_len; + dataset->resp.s_proto_len = s_proto_len; + dataset->resp.s_port = serv->s_port; + dataset->resp.s_aliases_cnt = s_aliases_cnt; + + cp = dataset->strdata; + + cp = mempcpy (cp, serv->s_name, s_name_len); + cp = mempcpy (cp, serv->s_proto, s_proto_len); + cp = mempcpy (cp, s_aliases_len, s_aliases_cnt * sizeof (uint32_t)); + + /* Then the aliases. */ + aliases = cp; + for (cnt = 0; cnt < s_aliases_cnt; ++cnt) + cp = mempcpy (cp, serv->s_aliases[cnt], s_aliases_len[cnt]); + + assert (cp + == dataset->strdata + total - offsetof (struct dataset, + strdata)); + + char *key_copy = memcpy (cp, key, req->key_len); + + /* Now we can determine whether on refill we have to create a new + record or not. */ + if (he != NULL) + { + assert (fd == -1); + + if (total + req->key_len == dh->allocsize + && total - offsetof (struct dataset, resp) == dh->recsize + && memcmp (&dataset->resp, dh->data, + dh->allocsize - offsetof (struct dataset, resp)) == 0) + { + /* The data has not changed. We will just bump the + timeout value. Note that the new record has been + allocated on the stack and need not be freed. */ + dh->timeout = dataset->head.timeout; + ++dh->nreloads; + } + else + { + /* We have to create a new record. Just allocate + appropriate memory and copy it. */ + struct dataset *newp + = (struct dataset *) mempool_alloc (db, total + req->key_len); + if (newp != NULL) + { + /* Adjust pointers into the memory block. */ + aliases = (char *) newp + (aliases - (char *) dataset); + if (key_copy != NULL) + key_copy = (char *) newp + (key_copy - (char *) dataset); + + dataset = memcpy (newp, dataset, total + req->key_len); + alloca_used = false; + } + + /* Mark the old record as obsolete. */ + dh->usable = false; + } + } + else + { + /* We write the dataset before inserting it to the database + since while inserting this thread might block and so would + unnecessarily keep the receiver waiting. */ + assert (fd != -1); + +#ifdef HAVE_SENDFILE + if (__builtin_expect (db->mmap_used, 1) && !alloca_used) + { + assert (db->wr_fd != -1); + assert ((char *) &dataset->resp > (char *) db->data); + assert ((char *) &dataset->resp - (char *) db->head + + total + <= (sizeof (struct database_pers_head) + + db->head->module * sizeof (ref_t) + + db->head->data_size)); + written = sendfileall (fd, db->wr_fd, + (char *) &dataset->resp + - (char *) db->head, total); +# ifndef __ASSUME_SENDFILE + if (written == -1 && errno == ENOSYS) + goto use_write; +# endif + } + else +# ifndef __ASSUME_SENDFILE + use_write: +# endif +#endif + written = writeall (fd, &dataset->resp, total); + } + + /* Add the record to the database. But only if it has not been + stored on the stack. */ + if (! alloca_used) + { + /* If necessary, we also propagate the data to disk. */ + if (db->persistent) + { + // XXX async OK? + uintptr_t pval = (uintptr_t) dataset & ~pagesize_m1; + msync ((void *) pval, + ((uintptr_t) dataset & pagesize_m1) + + total + req->key_len, MS_ASYNC); + } + + /* Now get the lock to safely insert the records. */ + pthread_rwlock_rdlock (&db->lock); + + if (cache_add (req->type, key_copy, req->key_len, + &dataset->head, true, db, owner) < 0) + /* Could not allocate memory. Make sure the + data gets discarded. */ + dataset->head.usable = false; + + pthread_rwlock_unlock (&db->lock); + } + } + + if (__builtin_expect (written != total, 0) && debug_level > 0) + { + char buf[256]; + dbg_log (_("short write in %s: %s"), __FUNCTION__, + strerror_r (errno, buf, sizeof (buf))); + } +} + + +static int +lookup (int type, char *key, struct servent *resultbufp, char *buffer, + size_t buflen, struct servent **serv) +{ + char *proto = strrchr (key, '/'); + if (proto != NULL && proto != key) + { + key = strndupa (key, proto - key); + if (proto[1] == '\0') + proto = NULL; + else + ++proto; + } + + if (type == GETSERVBYNAME) + return __getservbyname_r (key, proto, resultbufp, buffer, buflen, serv); + + assert (type == GETSERVBYPORT); + return __getservbyport_r (atol (key), proto, resultbufp, buffer, buflen, + serv); +} + + +static void +addservbyX (struct database_dyn *db, int fd, request_header *req, + char *key, uid_t uid, struct hashentry *he, struct datahead *dh) +{ + /* Search for the entry matching the key. Please note that we don't + look again in the table whether the dataset is now available. We + simply insert it. It does not matter if it is in there twice. The + pruning function only will look at the timestamp. */ + size_t buflen = 1024; + char *buffer = (char *) alloca (buflen); + struct servent resultbuf; + struct servent *serv; + bool use_malloc = false; + int errval = 0; + + if (__builtin_expect (debug_level > 0, 0)) + { + if (he == NULL) + dbg_log (_("Haven't found \"%s\" in services cache!"), key); + else + dbg_log (_("Reloading \"%s\" in services cache!"), key); + } + + while (lookup (req->type, key, &resultbuf, buffer, buflen, &serv) != 0 + && (errval = errno) == ERANGE) + { + errno = 0; + + if (__builtin_expect (buflen > 32768, 0)) + { + char *old_buffer = buffer; + buflen *= 2; + buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen); + if (buffer == NULL) + { + /* We ran out of memory. We cannot do anything but + sending a negative response. In reality this should + never happen. */ + serv = NULL; + buffer = old_buffer; + + /* We set the error to indicate this is (possibly) a + temporary error and that it does not mean the entry + is not available at all. */ + errval = EAGAIN; + break; + } + use_malloc = true; + } + else + /* Allocate a new buffer on the stack. If possible combine it + with the previously allocated buffer. */ + buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen); + } + + cache_addserv (db, fd, req, key, serv, uid, he, dh, errval); + + if (use_malloc) + free (buffer); +} + + +void +addservbyname (struct database_dyn *db, int fd, request_header *req, + void *key, uid_t uid) +{ + addservbyX (db, fd, req, key, uid, NULL, NULL); +} + + +void +readdservbyname (struct database_dyn *db, struct hashentry *he, + struct datahead *dh) +{ + request_header req = + { + .type = GETSERVBYNAME, + .key_len = he->len + }; + + addservbyX (db, -1, &req, db->data + he->key, he->owner, he, dh); +} + + +void +addservbyport (struct database_dyn *db, int fd, request_header *req, + void *key, uid_t uid) +{ + addservbyX (db, fd, req, key, uid, NULL, NULL); +} + + +void +readdservbyport (struct database_dyn *db, struct hashentry *he, + struct datahead *dh) +{ + request_header req = + { + .type = GETSERVBYPORT, + .key_len = he->len + }; + + addservbyX (db, -1, &req, db->data + he->key, he->owner, he, dh); +} diff --git a/nss/Versions b/nss/Versions index 463ffb5874..365f9e229b 100644 --- a/nss/Versions +++ b/nss/Versions @@ -9,7 +9,7 @@ libc { } GLIBC_PRIVATE { _nss_files_parse_grent; _nss_files_parse_pwent; _nss_files_parse_spent; - __nss_disable_nscd; __nss_lookup_function; + __nss_disable_nscd; __nss_lookup_function; __nss_services_lookup; } } diff --git a/nss/getent.c b/nss/getent.c index 14ec3c4755..8b9a9030ff 100644 --- a/nss/getent.c +++ b/nss/getent.c @@ -1,4 +1,4 @@ -/* Copyright (c) 1998-2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (c) 1998-2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. @@ -84,7 +84,7 @@ print_version (FILE *stream, struct argp_state *state) Copyright (C) %s Free Software Foundation, Inc.\n\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ -"), "2006"); +"), "2007"); fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk"); } diff --git a/nss/nsswitch.c b/nss/nsswitch.c index 21174dfbab..756204bd37 100644 --- a/nss/nsswitch.c +++ b/nss/nsswitch.c @@ -1,5 +1,4 @@ -/* Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. +/* Copyright (C) 1996-1999, 2001-2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -708,6 +707,7 @@ __nss_disable_nscd (void) __nss_not_use_nscd_passwd = -1; __nss_not_use_nscd_group = -1; __nss_not_use_nscd_hosts = -1; + __nss_not_use_nscd_services = -1; } diff --git a/posix/Makefile b/posix/Makefile index 311712d24e..8407ede093 100644 --- a/posix/Makefile +++ b/posix/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-1999, 2000-2005, 2006 Free Software Foundation, Inc. +# Copyright (C) 1991-1999, 2000-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 @@ -83,7 +83,7 @@ tests := tstgetopt testfnm runtests runptests \ bug-regex21 bug-regex22 bug-regex23 bug-regex24 \ 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 \ + 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 \ @@ -109,7 +109,7 @@ generated := $(addprefix wordexp-test-result, 1 2 3 4 5 6 7 8 9 10) \ 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 @@ -175,6 +175,7 @@ tst-exec-ARGS = -- $(built-program-cmd) 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 @@ -219,7 +220,7 @@ ifeq (no,$(cross-compiling)) 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 @@ -246,6 +247,11 @@ bug-regex21-ENV = MALLOC_TRACE=$(objpfx)bug-regex21.mtrace $(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. diff --git a/posix/execvp.c b/posix/execvp.c index 8421bd048f..887379e3a2 100644 --- a/posix/execvp.c +++ b/posix/execvp.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1991,92,1995-99,2002,2004,2005 Free Software Foundation, Inc. +/* Copyright (C) 1991,92, 1995-99, 2002, 2004, 2005, 2007 + Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,6 +17,7 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <alloca.h> #include <unistd.h> #include <stdarg.h> #include <stdbool.h> @@ -27,29 +29,18 @@ /* The file is accessible but it is not an executable file. Invoke the shell to interpret it as a script. */ -static char ** +static void internal_function -allocate_scripts_argv (const char *file, char *const argv[]) +scripts_argv (const char *file, char *const argv[], int argc, char **new_argv) { - /* Count the arguments. */ - int argc = 0; - while (argv[argc++]) - ; - /* Construct an argument list for the shell. */ - char **new_argv = (char **) malloc ((argc + 1) * sizeof (char *)); - if (new_argv != NULL) + new_argv[0] = (char *) _PATH_BSHELL; + new_argv[1] = (char *) file; + while (argc > 1) { - new_argv[0] = (char *) _PATH_BSHELL; - new_argv[1] = (char *) file; - while (argc > 1) - { - new_argv[argc] = argv[argc - 1]; - --argc; - } + new_argv[argc] = argv[argc - 1]; + --argc; } - - return new_argv; } @@ -67,8 +58,6 @@ execvp (file, argv) return -1; } - char **script_argv = NULL; - if (strchr (file, '/') != NULL) { /* Don't search when it contains a slash. */ @@ -76,46 +65,71 @@ execvp (file, argv) if (errno == ENOEXEC) { - script_argv = allocate_scripts_argv (file, argv); + /* Count the arguments. */ + int argc = 0; + while (argv[argc++]) + ; + size_t len = (argc + 1) * sizeof (char *); + char **script_argv; + void *ptr = NULL; + if (__libc_use_alloca (len)) + script_argv = alloca (len); + else + script_argv = ptr = malloc (len); + if (script_argv != NULL) { + scripts_argv (file, argv, argc, script_argv); __execve (script_argv[0], script_argv, __environ); - free (script_argv); + free (ptr); } } } else { + size_t pathlen; + size_t alloclen = 0; char *path = getenv ("PATH"); + if (path == NULL) + { + pathlen = confstr (_CS_PATH, (char *) NULL, 0); + alloclen = pathlen + 1; + } + else + pathlen = strlen (path); + + size_t len = strlen (file) + 1; + alloclen += pathlen + len + 1; + + char *name; char *path_malloc = NULL; + if (__libc_use_alloca (alloclen)) + name = alloca (alloclen); + else + { + path_malloc = name = malloc (alloclen); + if (name == NULL) + return -1; + } + if (path == NULL) { /* There is no `PATH' in the environment. The default search path is the current directory followed by the path `confstr' returns for `_CS_PATH'. */ - size_t len = confstr (_CS_PATH, (char *) NULL, 0); - path = (char *) malloc (1 + len); - if (path == NULL) - return -1; + path = name + pathlen + len + 1; path[0] = ':'; - (void) confstr (_CS_PATH, path + 1, len); - path_malloc = path; + (void) confstr (_CS_PATH, path + 1, pathlen); } - size_t len = strlen (file) + 1; - size_t pathlen = strlen (path); - char *name = malloc (pathlen + len + 1); - if (name == NULL) - { - free (path_malloc); - return -1; - } /* Copy the file name at the top. */ name = (char *) memcpy (name + pathlen + 1, file, len); /* And add the slash. */ *--name = '/'; + char **script_argv = NULL; + void *script_argv_malloc = NULL; bool got_eacces = false; char *p = path; do @@ -139,7 +153,15 @@ execvp (file, argv) { if (script_argv == NULL) { - script_argv = allocate_scripts_argv (startp, argv); + /* Count the arguments. */ + int argc = 0; + while (argv[argc++]) + ; + size_t arglen = (argc + 1) * sizeof (char *); + if (__libc_use_alloca (alloclen + arglen)) + script_argv = alloca (arglen); + else + script_argv = script_argv_malloc = malloc (arglen); if (script_argv == NULL) { /* A possible EACCES error is not as important as @@ -147,6 +169,7 @@ execvp (file, argv) got_eacces = false; break; } + scripts_argv (startp, argv, argc, script_argv); } __execve (script_argv[0], script_argv, __environ); @@ -184,11 +207,10 @@ execvp (file, argv) /* We tried every element and none of them worked. */ if (got_eacces) /* At least one failure was due to permissions, so report that - error. */ + error. */ __set_errno (EACCES); - free (script_argv); - free (name - pathlen); + free (script_argv_malloc); free (path_malloc); } diff --git a/posix/getconf.c b/posix/getconf.c index 3c5ffe454c..c7a9d57628 100644 --- a/posix/getconf.c +++ b/posix/getconf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 92, 1995-2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 1991, 92, 1995-2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. This program is free software; you can redistribute it and/or modify @@ -1008,7 +1008,7 @@ main (int argc, char *argv[]) Copyright (C) %s Free Software Foundation, Inc.\n\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ -"), "2006"); +"), "2007"); fprintf (stderr, gettext ("Written by %s.\n"), "Roland McGrath"); return 0; } diff --git a/posix/tst-vfork3.c b/posix/tst-vfork3.c new file mode 100644 index 0000000000..954d395fd2 --- /dev/null +++ b/posix/tst-vfork3.c @@ -0,0 +1,224 @@ +/* Test for vfork functions. + Copyright (C) 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2007. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <fcntl.h> +#include <mcheck.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> + +static int do_test (void); +static void do_prepare (void); +char *tmpdirname; + +#define TEST_FUNCTION do_test () +#define PREPARE(argc, argv) do_prepare () +#include "../test-skeleton.c" + +static int +do_test (void) +{ + mtrace (); + + const char *path = getenv ("PATH"); + if (path == NULL) + path = "/bin"; + char pathbuf[strlen (tmpdirname) + 1 + strlen (path) + 1]; + strcpy (stpcpy (stpcpy (pathbuf, tmpdirname), ":"), path); + if (setenv ("PATH", pathbuf, 1) < 0) + { + puts ("setenv failed"); + return 1; + } + + size_t i; + char *argv[3] = { (char *) "script1.sh", (char *) "1", NULL }; + for (i = 0; i < 5; i++) + { + pid_t pid = vfork (); + if (pid < 0) + { + printf ("vfork failed: %m\n"); + return 1; + } + else if (pid == 0) + { + execvp ("script1.sh", argv); + _exit (errno); + } + int status; + if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid) + { + puts ("waitpid failed"); + return 1; + } + else if (status != 0) + { + if (WIFEXITED (status)) + printf ("script1.sh failed with status %d\n", + WEXITSTATUS (status)); + else + printf ("script1.sh kill by signal %d\n", + WTERMSIG (status)); + return 1; + } + } + + argv[0] = (char *) "script2.sh"; + argv[1] = (char *) "2"; + for (i = 0; i < 5; i++) + { + pid_t pid = vfork (); + if (pid < 0) + { + printf ("vfork failed: %m\n"); + return 1; + } + else if (pid == 0) + { + execvp ("script2.sh", argv); + _exit (errno); + } + int status; + if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid) + { + puts ("waitpid failed"); + return 1; + } + else if (status != 0) + { + printf ("script2.sh failed with status %d\n", status); + return 1; + } + } + + for (i = 0; i < 5; i++) + { + pid_t pid = vfork (); + if (pid < 0) + { + printf ("vfork failed: %m\n"); + return 1; + } + else if (pid == 0) + { + execlp ("script2.sh", "script2.sh", "3", NULL); + _exit (errno); + } + int status; + if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid) + { + puts ("waitpid failed"); + return 1; + } + else if (status != 0) + { + printf ("script2.sh failed with status %d\n", status); + return 1; + } + } + + unsetenv ("PATH"); + argv[0] = (char *) "echo"; + argv[1] = (char *) "script 4"; + for (i = 0; i < 5; i++) + { + pid_t pid = vfork (); + if (pid < 0) + { + printf ("vfork failed: %m\n"); + return 1; + } + else if (pid == 0) + { + execvp ("echo", argv); + _exit (errno); + } + int status; + if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid) + { + puts ("waitpid failed"); + return 1; + } + else if (status != 0) + { + printf ("echo failed with status %d\n", status); + return 1; + } + } + + return 0; +} + +static void +do_prepare (void) +{ + size_t len = strlen (test_dir) + sizeof ("/tst-vfork3.XXXXXX"); + tmpdirname = malloc (len); + char *script1 = malloc (len + sizeof "/script1.sh"); + char *script2 = malloc (len + sizeof "/script2.sh"); + if (tmpdirname == NULL || script1 == NULL || script2 == NULL) + { + puts ("out of memory"); + exit (1); + } + strcpy (stpcpy (tmpdirname, test_dir), "/tst-vfork3.XXXXXX"); + + tmpdirname = mkdtemp (tmpdirname); + if (tmpdirname == NULL) + { + puts ("could not create temporary directory"); + exit (1); + } + + strcpy (stpcpy (script1, tmpdirname), "/script1.sh"); + strcpy (stpcpy (script2, tmpdirname), "/script2.sh"); + + /* Need to make sure tmpdirname is at the end of the linked list. */ + add_temp_file (script1); + add_temp_file (tmpdirname); + add_temp_file (script2); + + const char content1[] = "#!/bin/sh\necho script $1\n"; + int fd = open (script1, O_WRONLY | O_CREAT, 0700); + if (fd < 0 + || TEMP_FAILURE_RETRY (write (fd, content1, sizeof content1)) + != sizeof content1 + || fchmod (fd, S_IRUSR | S_IXUSR) < 0) + { + printf ("Could not write %s\n", script1); + exit (1); + } + close (fd); + + const char content2[] = "echo script $1\n"; + fd = open (script2, O_WRONLY | O_CREAT, 0700); + if (fd < 0 + || TEMP_FAILURE_RETRY (write (fd, content2, sizeof content2)) + != sizeof content2 + || fchmod (fd, S_IRUSR | S_IXUSR) < 0) + { + printf ("Could not write %s\n", script2); + exit (1); + } + close (fd); +} diff --git a/posix/wordexp.c b/posix/wordexp.c index adece95ef8..765d14d81f 100644 --- a/posix/wordexp.c +++ b/posix/wordexp.c @@ -1809,7 +1809,7 @@ envsubst: /* Substitute parameter */ break; - if (free_value && value) + if (free_value) free (value); if (!colon_seen && value) @@ -1827,7 +1827,7 @@ envsubst: case ACT_NONNULL_SUBST: if (value && (*value || !colon_seen)) { - if (free_value && value) + if (free_value) free (value); value = pattern ? __strdup (pattern) : pattern; diff --git a/scripts/check-local-headers.sh b/scripts/check-local-headers.sh index 88c85f7106..c2d6ba4a08 100755 --- a/scripts/check-local-headers.sh +++ b/scripts/check-local-headers.sh @@ -1,5 +1,5 @@ #! /bin/bash -# Copyright (C) 2005 Free Software Foundation, Inc. +# Copyright (C) 2005, 2007 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -26,7 +26,7 @@ cd "$objpfx" # Search all dependency files for file names in the include directory. # There are a few system headers we are known to use. -if fgrep "$includedir" */*.d | +if fgrep "$includedir" */*.{o,os,oS}.d | fgrep -v "$includedir/asm" | fgrep -v "$includedir/linux" | fgrep -v "$includedir/selinux" | diff --git a/soft-fp/op-4.h b/soft-fp/op-4.h index 34f5098e8c..1b90535c56 100644 --- a/soft-fp/op-4.h +++ b/soft-fp/op-4.h @@ -564,7 +564,7 @@ r1 = x1 - y1; \ _c2 = r1 > x1; \ r1 -= _c1; \ - _c2 |= r1 > _c1; \ + _c2 |= _c1 && (y1 == x1); \ r2 = x2 - y2 - _c2; \ } while (0) #endif @@ -578,11 +578,11 @@ r1 = x1 - y1; \ _c2 = r1 > x1; \ r1 -= _c1; \ - _c2 |= r1 > _c1; \ + _c2 |= _c1 && (y1 == x1); \ r2 = x2 - y2; \ _c3 = r2 > x2; \ r2 -= _c2; \ - _c3 |= r2 > _c2; \ + _c3 |= _c2 && (y2 == x2); \ r3 = x3 - y3 - _c3; \ } while (0) #endif diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h index 4ec7fade48..0aa6e3e05d 100644 --- a/soft-fp/op-common.h +++ b/soft-fp/op-common.h @@ -1,5 +1,5 @@ /* Software floating-point emulation. Common operations. - Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc. + Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@cygnus.com), Jakub Jelinek (jj@ultra.linux.cz), @@ -99,10 +99,10 @@ do { \ else \ { \ X##_e = _FP_EXPMAX_##fs - 1; \ - FP_SET_EXCEPTION(FP_EX_OVERFLOW); \ - FP_SET_EXCEPTION(FP_EX_INEXACT); \ _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc); \ } \ + FP_SET_EXCEPTION(FP_EX_INEXACT); \ + FP_SET_EXCEPTION(FP_EX_OVERFLOW); \ } while (0) /* Check for a semi-raw value being a signaling NaN and raise the @@ -1252,6 +1252,9 @@ do { \ _FP_FRAC_SRL_##swc(S, (_FP_WFRACBITS_##sfs \ - _FP_WFRACBITS_##dfs)); \ _FP_FRAC_COPY_##dwc##_##swc(D, S); \ + /* Semi-raw NaN must have all workbits cleared. */ \ + _FP_FRAC_LOW_##dwc(D) \ + &= ~(_FP_W_TYPE) ((1 << _FP_WORKBITS) - 1); \ _FP_FRAC_HIGH_##dfs(D) |= _FP_QNANBIT_SH_##dfs; \ } \ } \ diff --git a/stdlib/Makefile b/stdlib/Makefile index 2699ca61f6..b4518b2bb3 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-2002,2003,2004,2005,2006 Free Software Foundation, Inc. +# Copyright (C) 1991-2006, 2007 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -68,7 +68,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ 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-rand48-2 \ - tst-makecontext + tst-makecontext tst-strtod4 include ../Makeconfig @@ -113,6 +113,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. diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c index b4e4819c87..bb7493bff0 100644 --- a/stdlib/strtod_l.c +++ b/stdlib/strtod_l.c @@ -1,5 +1,6 @@ /* Convert string representing a number to float value, using given locale. - Copyright (C) 1997,1998,2002,2004,2005,2006 Free Software Foundation, Inc. + Copyright (C) 1997,1998,2002,2004,2005,2006,2007 + Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -650,10 +651,11 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc) 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, loc) 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'; }) + ({ 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, loc) break; if (thousands[cnt] != '\0') break; + cp += cnt - 1; } #endif } diff --git a/stdlib/tst-makecontext.c b/stdlib/tst-makecontext.c index cbce71fb92..1451efa56e 100644 --- a/stdlib/tst-makecontext.c +++ b/stdlib/tst-makecontext.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 Free Software Foundation, Inc. +/* Copyright (C) 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,6 +16,7 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <errno.h> #include <stdlib.h> #include <stdio.h> #include <ucontext.h> @@ -36,10 +37,16 @@ cf (int i) } int -main (void) +do_test (void) { if (getcontext (&ucp) != 0) { + if (errno == ENOSYS) + { + puts ("context handling not supported"); + return 0; + } + puts ("getcontext failed"); return 1; } @@ -47,7 +54,7 @@ main (void) ucp.uc_link = NULL; ucp.uc_stack.ss_sp = st1; ucp.uc_stack.ss_size = sizeof st1; - makecontext (&ucp, (void (*) ()) cf, 1, 78); + makecontext (&ucp, (void (*) (void)) cf, 1, 78); if (setcontext (&ucp) != 0) { puts ("setcontext failed"); @@ -55,3 +62,6 @@ main (void) } return 2; } + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/stdlib/tst-strtod2.c b/stdlib/tst-strtod2.c index 925ea9cafa..30d8d9df65 100644 --- a/stdlib/tst-strtod2.c +++ b/stdlib/tst-strtod2.c @@ -1,22 +1,41 @@ #include <stdio.h> #include <stdlib.h> +struct test +{ + const char *str; + double result; + size_t offset; +} tests[] = +{ + { "0xy", 0.0, 1 }, + { "0x.y", 0.0, 1 }, + { "0x0.y", 0.0, 4 }, + { "0x.0y", 0.0, 4 }, + { ".y", 0.0, 0 }, + { "0.y", 0.0, 2 }, + { ".0y", 0.0, 2 } +}; + static int do_test (void) { int status = 0; - const char s[] = "0x"; - char *ep; - double r = strtod (s, &ep); - if (r != 0) - { - printf ("r = %g, expect 0\n", r); - status = 1; - } - if (ep != s + 1) + for (size_t i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i) { - printf ("strtod parsed %ju characters, expected 1\n", ep - s); - status = 1; + char *ep; + double r = strtod (tests[i].str, &ep); + if (r != tests[i].result) + { + printf ("test %zu r = %g, expect %g\n", i, r, tests[i].result); + status = 1; + } + if (ep != tests[i].str + tests[i].offset) + { + printf ("test %zu strtod parsed %ju characters, expected %zu\n", + i, ep - tests[i].str, tests[i].offset); + status = 1; + } } return status; } diff --git a/stdlib/tst-strtod4.c b/stdlib/tst-strtod4.c new file mode 100644 index 0000000000..2d9d54c944 --- /dev/null +++ b/stdlib/tst-strtod4.c @@ -0,0 +1,56 @@ +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define NBSP "\xc2\xa0" + +static const struct +{ + const char *in; + const char *out; + double expected; +} tests[] = + { + { "000"NBSP"000"NBSP"000", "", 0.0 }, + { "1"NBSP"000"NBSP"000,5x", "x", 1000000.5 } + }; +#define NTESTS (sizeof (tests) / sizeof (tests[0])) + + +static int +do_test (void) +{ + if (setlocale (LC_ALL, "cs_CZ.UTF-8") == NULL) + { + puts ("could not set locale"); + return 1; + } + + int status = 0; + + for (int i = 0; i < NTESTS; ++i) + { + char *ep; + double r = __strtod_internal (tests[i].in, &ep, 1); + + if (strcmp (ep, tests[i].out) != 0) + { + printf ("%d: got rest string \"%s\", expected \"%s\"\n", + i, ep, tests[i].out); + status = 1; + } + + if (r != tests[i].expected) + { + printf ("%d: got wrong results %g, expected %g\n", + i, r, tests[i].expected); + status = 1; + } + } + + return status; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/string/Makefile b/string/Makefile index 3e79f4d909..f087022b3c 100644 --- a/string/Makefile +++ b/string/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-2002, 2005, 2006 Free Software Foundation, Inc. +# Copyright (C) 1991-2002, 2005, 2006, 2007 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -64,6 +64,7 @@ tester-ENV = LANGUAGE=C inl-tester-ENV = LANGUAGE=C noinl-tester-ENV = LANGUAGE=C tst-strxfrm-ENV = LOCPATH=$(common-objpfx)localedata +tst-strxfrm2-ENV = LOCPATH=$(common-objpfx)localedata bug-strcoll1-ENV = LOCPATH=$(common-objpfx)localedata CFLAGS-inl-tester.c = -fno-builtin CFLAGS-noinl-tester.c = -fno-builtin diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index dda91bb806..a9d20b2150 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1,5 +1,5 @@ /* Run-time dynamic linker data structures for loaded ELF shared objects. - Copyright (C) 1995-2003, 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1995-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 @@ -838,7 +838,9 @@ enum DL_LOOKUP_ADD_DEPENDENCY = 1, /* Return most recent version instead of default version for unversioned lookup. */ - DL_LOOKUP_RETURN_NEWEST = 2 + DL_LOOKUP_RETURN_NEWEST = 2, + /* Set if the scopr lock in the UNDEF_MAP is taken. */ + DL_LOOKUP_SCOPE_LOCK = 4 }; /* Lookup versioned symbol. */ @@ -847,7 +849,7 @@ extern lookup_t _dl_lookup_symbol_x (const char *undef, const ElfW(Sym) **sym, struct r_scope_elem *symbol_scope[], const struct r_found_version *version, - int type_class, int explicit, + int type_class, int flags, struct link_map *skip_map) internal_function attribute_hidden; diff --git a/sysdeps/i386/i486/bits/atomic.h b/sysdeps/i386/i486/bits/atomic.h index a27734c37e..4577499d58 100644 --- a/sysdeps/i386/i486/bits/atomic.h +++ b/sysdeps/i386/i486/bits/atomic.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -56,26 +56,33 @@ typedef uintmax_t uatomic_max_t; #endif -#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ +#if __GNUC_PREREQ (4, 1) +# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + __sync_val_compare_and_swap (mem, oldval, newval) +# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ + (! __sync_bool_compare_and_swap (mem, oldval, newval)) +#else +# define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ ({ __typeof (*mem) ret; \ __asm __volatile (LOCK_PREFIX "cmpxchgb %b2, %1" \ : "=a" (ret), "=m" (*mem) \ : "q" (newval), "m" (*mem), "0" (oldval)); \ ret; }) -#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ +# define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ ({ __typeof (*mem) ret; \ __asm __volatile (LOCK_PREFIX "cmpxchgw %w2, %1" \ : "=a" (ret), "=m" (*mem) \ : "r" (newval), "m" (*mem), "0" (oldval)); \ ret; }) -#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ +# define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ ({ __typeof (*mem) ret; \ __asm __volatile (LOCK_PREFIX "cmpxchgl %2, %1" \ : "=a" (ret), "=m" (*mem) \ : "r" (newval), "m" (*mem), "0" (oldval)); \ ret; }) +#endif #define __arch_c_compare_and_exchange_val_8_acq(mem, newval, oldval) \ @@ -240,8 +247,13 @@ typedef uintmax_t uatomic_max_t; } \ __result; }) -#define atomic_exchange_and_add(mem, value) \ +#if __GNUC_PREREQ (4, 1) +# define atomic_exchange_and_add(mem, value) \ + __sync_fetch_and_add (mem, value) +#else +# define atomic_exchange_and_add(mem, value) \ __arch_exchange_and_add_body (LOCK_PREFIX, __arch, mem, value) +#endif #define __arch_exchange_and_add_cprefix \ "cmpl $0, %%gs:%P4\n\tje 0f\n\tlock\n0:\t" diff --git a/sysdeps/i386/soft-fp/sfp-machine.h b/sysdeps/i386/soft-fp/sfp-machine.h deleted file mode 100644 index ed71ae418a..0000000000 --- a/sysdeps/i386/soft-fp/sfp-machine.h +++ /dev/null @@ -1,89 +0,0 @@ -#define _FP_W_TYPE_SIZE 32 -#define _FP_W_TYPE unsigned long -#define _FP_WS_TYPE signed long -#define _FP_I_TYPE long - -#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \ - __asm__("addl %5,%1; adcl %3,%0" \ - : "=r"(rh), "=r"(rl) \ - : "%0"(xh), "g"(yh), "%1"(xl), "g"(yl) \ - : "cc") - -#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ - do { \ - __asm__ volatile("addl %5,%1; adcl %3,%0" \ - : "=r"(r1), "=r"(r0) \ - : "%0"(x1), "g"(y1), "%1"(x0), "g"(y0) \ - : "cc"); \ - __asm__ volatile("adcl %5,%1; adcl %3,%0" \ - : "=r"(r3), "=r"(r2) \ - : "%0"(x3), "g"(y3), "%1"(x2), "g"(y2) \ - : "cc"); \ - } while (0) - -#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \ - __asm__("subl %5,%1; sbbl %4,%0" \ - : "=r"(rh), "=r"(rl) \ - : "0"(xh), "1"(xl), "g"(yh), "g"(yl) \ - : "cc") - -#define __FP_CLZ(r, x) \ - do { \ - __asm__("bsrl %1,%0" : "=r"(r) : "g"(x) : "cc"); \ - r ^= 31; \ - } while (0) - -#define _i386_mul_32_64(rh, rl, x, y) \ - __asm__("mull %2" : "=d"(rh), "=a"(rl) : "%g"(x), "1"(y) : "cc") - -#define _i386_div_64_32(q, r, nh, nl, d) \ - __asm__ ("divl %4" : "=a"(q), "=d"(r) : "0"(nl), "1"(nh), "g"(d) : "cc") - - -#define _FP_MUL_MEAT_S(R,X,Y) \ - _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,_i386_mul_32_64) -#define _FP_MUL_MEAT_D(R,X,Y) \ - _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,_i386_mul_32_64) - -#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv(S,R,X,Y) -#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y) - -#define _FP_NANFRAC_S _FP_QNANBIT_S -#define _FP_NANFRAC_D _FP_QNANBIT_D, 0 -#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0, 0, 0 -#define _FP_NANSIGN_S 1 -#define _FP_NANSIGN_D 1 -#define _FP_NANSIGN_Q 1 - -#define _FP_KEEPNANFRACP 1 -/* Here is something Intel misdesigned: the specs don't define - the case where we have two NaNs with same mantissas, but - different sign. Different operations pick up different NaNs. - */ -#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ - do { \ - if (_FP_FRAC_GT_##wc(X, Y) \ - || (_FP_FRAC_EQ_##wc(X,Y) && (OP == '+' || OP == '*'))) \ - { \ - R##_s = X##_s; \ - _FP_FRAC_COPY_##wc(R,X); \ - } \ - else \ - { \ - R##_s = Y##_s; \ - _FP_FRAC_COPY_##wc(R,Y); \ - } \ - R##_c = FP_CLS_NAN; \ - } while (0) - -#define FP_EX_INVALID (1 << 0) -#define FP_EX_DENORM (1 << 1) -#define FP_EX_DIVZERO (1 << 2) -#define FP_EX_OVERFLOW (1 << 3) -#define FP_EX_UNDERFLOW (1 << 4) -#define FP_EX_INEXACT (1 << 5) - -#define FP_RND_NEAREST 0 -#define FP_RND_ZERO 3 -#define FP_RND_PINF 2 -#define FP_RND_MINF 1 diff --git a/sysdeps/posix/system.c b/sysdeps/posix/system.c index f63dde4dae..e78195ef82 100644 --- a/sysdeps/posix/system.c +++ b/sysdeps/posix/system.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2000, 2002, 2003, 2005 Free Software Foundation, Inc. +/* Copyright (C) 1991-2000,2002,2003,2005,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -143,27 +143,11 @@ do_system (const char *line) else /* Parent side. */ { -#ifdef NO_WAITPID - pid_t child; - do - { - child = __wait (&status); - if (child <= -1 && errno != EINTR) - { - status = -1; - break; - } - /* Note that pid cannot be <= -1 and therefore the loop continues - when __wait returned with EINTR. */ - } - while (child != pid); -#else /* Note the system() is a cancellation point. But since we call waitpid() which itself is a cancellation point we do not have to do anything here. */ if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) != pid) status = -1; -#endif } #ifdef CLEANUP_HANDLER diff --git a/sysdeps/unix/sysv/linux/fatal-prepare.h b/sysdeps/unix/sysv/linux/fatal-prepare.h index d48ae625ee..81f38b09ee 100644 --- a/sysdeps/unix/sysv/linux/fatal-prepare.h +++ b/sysdeps/unix/sysv/linux/fatal-prepare.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -24,10 +24,9 @@ # include <pthread-functions.h> # define FATAL_PREPARE \ { \ - int (*fp) (int, int *); \ - fp = __libc_pthread_functions.ptr_pthread_setcancelstate; \ - if (fp != NULL) \ - fp (PTHREAD_CANCEL_DISABLE, NULL); \ + if (__libc_pthread_functions_init) \ + PTHFCT_CALL (ptr_pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, \ + NULL)); \ } #else # pragma weak pthread_setcancelstate diff --git a/sysdeps/unix/sysv/linux/sh/bits/shm.h b/sysdeps/unix/sysv/linux/sh/bits/shm.h new file mode 100644 index 0000000000..189179394b --- /dev/null +++ b/sysdeps/unix/sysv/linux/sh/bits/shm.h @@ -0,0 +1,101 @@ +/* Copyright (C) 1995,1996,1997,2000,2002,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. */ + +#ifndef _SYS_SHM_H +# error "Never include <bits/shm.h> directly; use <sys/shm.h> instead." +#endif + +#include <bits/types.h> + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from <linux/stat.h> */ +#define SHM_W 0200 /* or S_IWUGO from <linux/stat.h> */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA 0x4000 + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + unsigned long int __unused1; + __time_t shm_dtime; /* time of last shmdt() */ + unsigned long int __unused2; + __time_t shm_ctime; /* time of last change by shmctl() */ + unsigned long int __unused3; + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/sysdeps/x86_64/bits/atomic.h b/sysdeps/x86_64/bits/atomic.h index 65d6b02008..80e8a0bccb 100644 --- a/sysdeps/x86_64/bits/atomic.h +++ b/sysdeps/x86_64/bits/atomic.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -56,34 +56,41 @@ typedef uintmax_t uatomic_max_t; #endif -#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ +#if __GNUC_PREREQ (4, 1) +# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + __sync_val_compare_and_swap (mem, oldval, newval) +# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ + (! __sync_bool_compare_and_swap (mem, oldval, newval)) +#else +# define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ ({ __typeof (*mem) ret; \ __asm __volatile (LOCK_PREFIX "cmpxchgb %b2, %1" \ : "=a" (ret), "=m" (*mem) \ : "q" (newval), "m" (*mem), "0" (oldval)); \ ret; }) -#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ +# define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ ({ __typeof (*mem) ret; \ __asm __volatile (LOCK_PREFIX "cmpxchgw %w2, %1" \ : "=a" (ret), "=m" (*mem) \ : "r" (newval), "m" (*mem), "0" (oldval)); \ ret; }) -#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ +# define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ ({ __typeof (*mem) ret; \ __asm __volatile (LOCK_PREFIX "cmpxchgl %2, %1" \ : "=a" (ret), "=m" (*mem) \ : "r" (newval), "m" (*mem), "0" (oldval)); \ ret; }) -#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ +# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ ({ __typeof (*mem) ret; \ __asm __volatile (LOCK_PREFIX "cmpxchgq %q2, %1" \ : "=a" (ret), "=m" (*mem) \ : "r" ((long int) (newval)), "m" (*mem), \ "0" ((long int) (oldval))); \ ret; }) +#endif #define __arch_c_compare_and_exchange_val_8_acq(mem, newval, oldval) \ @@ -178,8 +185,13 @@ typedef uintmax_t uatomic_max_t; "i" (offsetof (tcbhead_t, multiple_threads))); \ result; }) -#define atomic_exchange_and_add(mem, value) \ +#if __GNUC_PREREQ (4, 1) +# define atomic_exchange_and_add(mem, value) \ + __sync_fetch_and_add (mem, value) +#else +# define atomic_exchange_and_add(mem, value) \ __arch_exchange_and_add_body (LOCK_PREFIX, mem, value) +#endif #define __arch_exchange_and_add_cprefix \ "cmpl $0, %%fs:%P4\n\tje 0f\n\tlock\n0:\t" diff --git a/sysdeps/x86_64/soft-fp/sfp-machine.h b/sysdeps/x86_64/soft-fp/sfp-machine.h deleted file mode 100644 index 77df02380c..0000000000 --- a/sysdeps/x86_64/soft-fp/sfp-machine.h +++ /dev/null @@ -1,51 +0,0 @@ -#define _FP_W_TYPE_SIZE 64 -#define _FP_W_TYPE unsigned long -#define _FP_WS_TYPE signed long -#define _FP_I_TYPE long - -#define __FP_CLZ(r, x) \ - do { \ - __asm__("bsrq %1,%0" : "=r"(r) : "g"(x) : "cc"); \ - r ^= 63; \ - } while (0) - -#define _FP_NANFRAC_S _FP_QNANBIT_S -#define _FP_NANFRAC_D _FP_QNANBIT_D, 0 -#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0, 0, 0 -#define _FP_NANSIGN_S 1 -#define _FP_NANSIGN_D 1 -#define _FP_NANSIGN_Q 1 - -#define _FP_KEEPNANFRACP 1 -/* Here is something Intel misdesigned: the specs don't define - the case where we have two NaNs with same mantissas, but - different sign. Different operations pick up different NaNs. - */ -#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ - do { \ - if (_FP_FRAC_GT_##wc(X, Y) \ - || (_FP_FRAC_EQ_##wc(X,Y) && (OP == '+' || OP == '*'))) \ - { \ - R##_s = X##_s; \ - _FP_FRAC_COPY_##wc(R,X); \ - } \ - else \ - { \ - R##_s = Y##_s; \ - _FP_FRAC_COPY_##wc(R,Y); \ - } \ - R##_c = FP_CLS_NAN; \ - } while (0) - -#define FP_EX_INVALID (1 << 0) -#define FP_EX_DENORM (1 << 1) -#define FP_EX_DIVZERO (1 << 2) -#define FP_EX_OVERFLOW (1 << 3) -#define FP_EX_UNDERFLOW (1 << 4) -#define FP_EX_INEXACT (1 << 5) - -#define FP_RND_NEAREST 0 -#define FP_RND_ZERO 3 -#define FP_RND_PINF 2 -#define FP_RND_MINF 1 - |