diff options
author | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2007-01-15 00:45:23 +0000 |
---|---|---|
committer | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2007-01-15 00:45:23 +0000 |
commit | 4fa8118022b19670c3f2a6f3dbc4d7b6b7df063c (patch) | |
tree | dd5d3b906d86c19a009739f46c6d5bbfd05e87b7 /libc | |
parent | 165be16219a0f9ad296f68fd805252e18c05e971 (diff) | |
download | eglibc2-4fa8118022b19670c3f2a6f3dbc4d7b6b7df063c.tar.gz |
Merge changes between r1147 and r1192 from /fsf/trunk.
git-svn-id: svn://svn.eglibc.org/trunk@1193 7b3dc134-2b1b-0410-93df-9e9f96275f8d
Diffstat (limited to 'libc')
42 files changed, 1337 insertions, 344 deletions
diff --git a/libc/ChangeLog b/libc/ChangeLog index 4e9dabaca..fff37d557 100644 --- a/libc/ChangeLog +++ b/libc/ChangeLog @@ -1,3 +1,102 @@ +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. @@ -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/libc/include/string.h b/libc/include/string.h index c196007dc..f73bbf9f4 100644 --- a/libc/include/string.h +++ b/libc/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/libc/inet/Makefile b/libc/inet/Makefile index 075716fbe..ad90b0619 100644 --- a/libc/inet/Makefile +++ b/libc/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/libc/io/fts.c b/libc/io/fts.c index 532743fb3..8e628b481 100644 --- a/libc/io/fts.c +++ b/libc/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/libc/nis/nss_nis/nis-service.c b/libc/nis/nss_nis/nis-service.c index 0c176095c..59a598f29 100644 --- a/libc/nis/nss_nis/nis-service.c +++ b/libc/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/libc/nptl/ChangeLog b/libc/nptl/ChangeLog index 631e20ddb..eb77263d5 100644 --- a/libc/nptl/ChangeLog +++ b/libc/nptl/ChangeLog @@ -1,3 +1,28 @@ +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 @@ -71,7 +96,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/libc/nptl/shlib-versions b/libc/nptl/shlib-versions index 5e18753be..06ac620f0 100644 --- a/libc/nptl/shlib-versions +++ b/libc/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/libc/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c b/libc/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c index 7613863bb..55d20eb8f 100644 --- a/libc/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c +++ b/libc/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/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h index 97085bf01..bb988f3b2 100644 --- a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h +++ b/libc/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/libc/nptl/tst-rwlock7.c b/libc/nptl/tst-rwlock7.c index 1f34c0650..369135b22 100644 --- a/libc/nptl/tst-rwlock7.c +++ b/libc/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/libc/nscd/Makefile b/libc/nscd/Makefile index 21657abeb..ef3ce184f 100644 --- a/libc/nscd/Makefile +++ b/libc/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/libc/nscd/cache.c b/libc/nscd/cache.c index ef986f374..e63a4f87d 100644 --- a/libc/nscd/cache.c +++ b/libc/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. @@ -328,51 +347,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/libc/nscd/connections.c b/libc/nscd/connections.c index 39d491a5e..a5e758e07 100644 --- a/libc/nscd/connections.c +++ b/libc/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,6 +157,25 @@ 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 } }; @@ -170,7 +195,10 @@ static struct database_dyn *const serv2db[LASTREQ] = [GETFDGR] = &dbs[grpdb], [GETFDHST] = &dbs[hstdb], [GETAI] = &dbs[hstdb], - [INITGROUPS] = &dbs[grpdb] + [INITGROUPS] = &dbs[grpdb], + [GETSERVBYNAME] = &dbs[servdb], + [GETSERVBYPORT] = &dbs[servdb], + [GETFDSERV] = &dbs[servdb] }; @@ -305,7 +333,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); @@ -821,18 +849,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)); @@ -911,8 +937,9 @@ cannot handle old request version %d; current version is %d"), 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 + && __builtin_expect (req->type >= GETPWBYNAME, 1) + && __builtin_expect (req->type < LASTREQ, 1) + && __builtin_expect (req->type < SHUTDOWN || req->type > INVALIDATE, 1) && nscd_request_avc_has_perm (fd, req->type) != 0) return; @@ -921,8 +948,9 @@ cannot handle old request version %d; current version is %d"), // 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) + && __builtin_expect (req->type, GETHOSTBYADDRv6) <= GETHOSTBYADDRv6) + || req->type == GETAI || req->type == INITGROUPS + || req->type == GETSERVBYNAME || req->type == GETSERVBYPORT) { if (__builtin_expect (debug_level, 0) > 0) { @@ -1066,6 +1094,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,6 +1147,7 @@ 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); #endif @@ -1152,7 +1189,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/libc/nscd/gai.c b/libc/nscd/gai.c index 2e706bdfe..46f8b8bec 100644 --- a/libc/nscd/gai.c +++ b/libc/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/libc/nscd/getsrvbynm_r.c b/libc/nscd/getsrvbynm_r.c new file mode 100644 index 000000000..fb60f4802 --- /dev/null +++ b/libc/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/libc/nscd/getsrvbypt_r.c b/libc/nscd/getsrvbypt_r.c new file mode 100644 index 000000000..fd5b11bc3 --- /dev/null +++ b/libc/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/libc/nscd/grpcache.c b/libc/nscd/grpcache.c index 5a8fba475..54d1ef1ee 100644 --- a/libc/nscd/grpcache.c +++ b/libc/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/libc/nscd/hstcache.c b/libc/nscd/hstcache.c index e27ece5bc..742491aea 100644 --- a/libc/nscd/hstcache.c +++ b/libc/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/libc/nscd/nscd-client.h b/libc/nscd/nscd-client.h index 0fd2d9f54..7702f590b 100644 --- a/libc/nscd/nscd-client.h +++ b/libc/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/libc/nscd/nscd.c b/libc/nscd/nscd.c index b68ae2f41..d0c34eb01 100644 --- a/libc/nscd/nscd.c +++ b/libc/nscd/nscd.c @@ -332,15 +332,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; diff --git a/libc/nscd/nscd.conf b/libc/nscd/nscd.conf index 43969898f..d0d16ad96 100644 --- a/libc/nscd/nscd.conf +++ b/libc/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/libc/nscd/nscd.h b/libc/nscd/nscd.h index 5c2ff3a95..e8199b800 100644 --- a/libc/nscd/nscd.h +++ b/libc/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/libc/nscd/nscd_conf.c b/libc/nscd/nscd_conf.c index 2048eca88..e724c6bd5 100644 --- a/libc/nscd/nscd_conf.c +++ b/libc/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/libc/nscd/nscd_gethst_r.c b/libc/nscd/nscd_gethst_r.c index 516977bcc..e83e4823e 100644 --- a/libc/nscd/nscd_gethst_r.c +++ b/libc/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/libc/nscd/nscd_getserv_r.c b/libc/nscd/nscd_getserv_r.c new file mode 100644 index 000000000..ea5dcedb8 --- /dev/null +++ b/libc/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/libc/nscd/nscd_proto.h b/libc/nscd/nscd_proto.h index 64d9bd004..573ca2b2e 100644 --- a/libc/nscd/nscd_proto.h +++ b/libc/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/libc/nscd/pwdcache.c b/libc/nscd/pwdcache.c index 01c223add..0461ec91c 100644 --- a/libc/nscd/pwdcache.c +++ b/libc/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/libc/nscd/selinux.c b/libc/nscd/selinux.c index f0620d101..4a462223f 100644 --- a/libc/nscd/selinux.c +++ b/libc/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/libc/nscd/servicescache.c b/libc/nscd/servicescache.c new file mode 100644 index 000000000..ea4fa3510 --- /dev/null +++ b/libc/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/libc/nss/Versions b/libc/nss/Versions index 463ffb587..365f9e229 100644 --- a/libc/nss/Versions +++ b/libc/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/libc/nss/nsswitch.c b/libc/nss/nsswitch.c index 21174dfba..756204bd3 100644 --- a/libc/nss/nsswitch.c +++ b/libc/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/libc/scripts/check-local-headers.sh b/libc/scripts/check-local-headers.sh index 88c85f710..c2d6ba4a0 100755 --- a/libc/scripts/check-local-headers.sh +++ b/libc/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/libc/stdlib/Makefile b/libc/stdlib/Makefile index f6648355c..b4518b2bb 100644 --- a/libc/stdlib/Makefile +++ b/libc/stdlib/Makefile @@ -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 @@ -114,6 +114,7 @@ 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/libc/stdlib/strtod_l.c b/libc/stdlib/strtod_l.c index b4e4819c8..bb7493bff 100644 --- a/libc/stdlib/strtod_l.c +++ b/libc/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/libc/stdlib/tst-makecontext.c b/libc/stdlib/tst-makecontext.c index cbce71fb9..1451efa56 100644 --- a/libc/stdlib/tst-makecontext.c +++ b/libc/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/libc/stdlib/tst-strtod2.c b/libc/stdlib/tst-strtod2.c index 925ea9caf..30d8d9df6 100644 --- a/libc/stdlib/tst-strtod2.c +++ b/libc/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/libc/stdlib/tst-strtod4.c b/libc/stdlib/tst-strtod4.c new file mode 100644 index 000000000..2d9d54c94 --- /dev/null +++ b/libc/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/libc/sysdeps/i386/i486/bits/atomic.h b/libc/sysdeps/i386/i486/bits/atomic.h index a27734c37..4577499d5 100644 --- a/libc/sysdeps/i386/i486/bits/atomic.h +++ b/libc/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/libc/sysdeps/i386/soft-fp/sfp-machine.h b/libc/sysdeps/i386/soft-fp/sfp-machine.h deleted file mode 100644 index ed71ae418..000000000 --- a/libc/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/libc/sysdeps/x86_64/bits/atomic.h b/libc/sysdeps/x86_64/bits/atomic.h index 65d6b0200..80e8a0bcc 100644 --- a/libc/sysdeps/x86_64/bits/atomic.h +++ b/libc/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/libc/sysdeps/x86_64/soft-fp/sfp-machine.h b/libc/sysdeps/x86_64/soft-fp/sfp-machine.h deleted file mode 100644 index 77df02380..000000000 --- a/libc/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 - |