diff options
-rw-r--r-- | ChangeLog | 98 | ||||
-rw-r--r-- | elf/cache.c | 1 | ||||
-rw-r--r-- | fedora/branch.mk | 4 | ||||
-rw-r--r-- | fedora/glibc.spec.in | 8 | ||||
-rw-r--r-- | iconv/gconv_simple.c | 16 | ||||
-rw-r--r-- | include/features.h | 15 | ||||
-rw-r--r-- | include/stdio.h | 1 | ||||
-rw-r--r-- | include/time.h | 3 | ||||
-rw-r--r-- | intl/dcigettext.c | 1 | ||||
-rw-r--r-- | libio/Makefile | 4 | ||||
-rw-r--r-- | libio/__freading.c | 5 | ||||
-rw-r--r-- | libio/ftello.c | 3 | ||||
-rw-r--r-- | libio/tst-ext2.c | 58 | ||||
-rw-r--r-- | locale/programs/ld-collate.c | 62 | ||||
-rw-r--r-- | locale/programs/repertoire.c | 3 | ||||
-rw-r--r-- | misc/Makefile | 2 | ||||
-rw-r--r-- | nscd/nscd_getai.c | 4 | ||||
-rw-r--r-- | nscd/nscd_getgr_r.c | 76 | ||||
-rw-r--r-- | nscd/nscd_gethst_r.c | 4 | ||||
-rw-r--r-- | nscd/nscd_getpw_r.c | 4 | ||||
-rw-r--r-- | nscd/nscd_getserv_r.c | 4 | ||||
-rw-r--r-- | nscd/nscd_helper.c | 103 | ||||
-rw-r--r-- | posix/fnmatch_loop.c | 13 | ||||
-rw-r--r-- | posix/regcomp.c | 10 | ||||
-rw-r--r-- | posix/regexec.c | 14 | ||||
-rw-r--r-- | sysdeps/posix/getaddrinfo.c | 9 | ||||
-rw-r--r-- | time/tzfile.c | 249 | ||||
-rw-r--r-- | time/tzset.c | 230 | ||||
-rw-r--r-- | timezone/tst-timezone.c | 3 |
29 files changed, 655 insertions, 352 deletions
diff --git a/ChangeLog b/ChangeLog index b9a90cd04d..619b6f2054 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,101 @@ +2007-10-14 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/posix/getaddrinfo.c (struct sort_result): Add + service_order. + (rfc3484_sort): Make sure that even of qsort doesn't support + stable sorting it is stable by comparing service_order. + (getaddrinfo): Initialize service_order. + + * include/time.h: Declare __tzset_parse_tz and __tzset_compute. + * time/tzset.c (tzset_internal): Break TZ string parsing out into + __tzset_parse_tz and updating of daylight, timezone, tzname into + update_vars. + (__tz_compute): Renamed from tz_compute. Take additional parameters. + (__tz_convert): Updating of tm_isdst, tm_zone, and tm_gmtoff now + happens in __tz_compute. + * time/tzfile.c (__tzfile_read): Also read TZ string. + (find_transition): Fold into __tzfile_compute. + (__tzfile_compute): For times beyond the last transition try to + use the TZ string. + * timezone/tst-timezone.c: Information in daylight and tzname does + change for Asia/Tokyo timezone with more concrete information. + Remove the test. + + * include/stdio.h: Add libc_hidden_proto for ftello. + * libio/ftello.c: Add libc_hidden_def. + + [BZ #1140] + * time/tzfile.c (__tzfile_compute): Compute tzname[] values based + on the specified time and not the last entries in the file. Move + code to determine tzname[] to... + (find_transition): ...here. Add ugly guess for times before the + first transition. + +2007-10-13 Ulrich Drepper <drepper@redhat.com> + + [BZ #3195] + * nscd/nscd_getai.c (__nscd_getai): Set errno to 0 in case we found + no entry. + * nscd/nscd_getgr.c (nscd_getgr_r): Likewise. + * nscd/nscd_gethst_r.c (nscd_gethst_r): Likewise. + * nscd/nscd_getpw_r.c (nscd_getpw_r): Likewise. + * nscd/nscd_getserv_r.c (nscd_getserv_r): Likewise. + + * nscd/nscd_getgr_r.c (nscd_getgr_r): Optimize a bit: use simpler + read mechanism when there are no group members and avoid no-op + read syscall in this case. + + [BZ #3242] + * nscd/nscd_helper.c (wait_on_socket): Take timeout as parameter. + (__readall): If reading failed due to EAGAIN error wait a bit + and possibly try again. + (__readvall): Likewise. + +2007-10-13 Bruno Haible <bruno@clisp.org> + + * intl/dcigettext.c (_nl_find_msg): Unlock the conversions_lock + when we cannot recode the message. + +2007-10-13 Ulrich Drepper <drepper@redhat.com> + + [BZ #4359] + * libio/__freading.c (__freading): Don't return true for + write-only streams. For read/write streams, check whether we + performed a read operation already. + * libio/Makefile (tests): Add tst-ext2. + * libio/tst-ext2.c: New file. + +2007-10-12 Ulrich Drepper <drepper@redhat.com> + + * locale/programs/repertoire.c (repertoire_read): Always free + memory for repertoire file name [Coverity CID 270]. + + * elf/cache.c (save_aux_cache): Free memory allocated for + temporary file name [Coverity CID 267]. + +2007-10-12 Jakub Jelinek <jakub@redhat.com> + + * misc/Makefile (headers): Add bits/error.h. + +2007-10-12 Ulrich Drepper <drepper@redhat.com> + + * posix/fnmatch_loop.c: Take rule index returned as part of + findidx return value into account when accessing weights. + * posix/regcomp.c: Likewise. + * posix/regexec.c: Likewise. + + * locale/programs/ld-collate.c (collate_read): Optimize a bit. + (skip_to): Fix problems with parameter of elifdef/elifndef. + +2007-10-11 Ulrich Drepper <drepper@redhat.com> + + * iconv/gconv_simple.c: Add some branch prediction. + +2007-10-12 Jakub Jelinek <jakub@redhat.com> + + * locale/programs/ld-collate.c (collate_read): If ignore_content + and nowtok is tok_define, eat any tok_eol tokens. + 2007-10-11 Jakub Jelinek <jakub@redhat.com> * sysdeps/gnu/netinet/tcp.h: Include sys/socket.h if __USE_MISC. diff --git a/elf/cache.c b/elf/cache.c index 9a600ea535..b8561e4b5f 100644 --- a/elf/cache.c +++ b/elf/cache.c @@ -800,5 +800,6 @@ save_aux_cache (const char *aux_cache_name) out_fail: /* Free allocated memory. */ + free (temp_name); free (file_entries); } diff --git a/fedora/branch.mk b/fedora/branch.mk index ac6349ee5d..c9056799ce 100644 --- a/fedora/branch.mk +++ b/fedora/branch.mk @@ -3,5 +3,5 @@ glibc-branch := fedora glibc-base := HEAD DIST_BRANCH := devel COLLECTION := dist-f8 -fedora-sync-date := 2007-10-11 16:36 UTC -fedora-sync-tag := fedora-glibc-20071011T1636 +fedora-sync-date := 2007-10-14 18:47 UTC +fedora-sync-tag := fedora-glibc-20071014T1847 diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in index 11d7d0eacd..084231ca17 100644 --- a/fedora/glibc.spec.in +++ b/fedora/glibc.spec.in @@ -1,4 +1,4 @@ -%define glibcrelease 19 +%define glibcrelease 20 %define run_glibc_tests 1 %define auxarches i586 i686 athlon sparcv9v sparc64v alphaev6 %define xenarches i686 athlon @@ -1010,6 +1010,12 @@ rm -f *.filelist* %endif %changelog +* Sun Oct 14 2007 Jakub Jelinek <jakub@redhat.com> 2.6.90-20 +- install <bits/error.h> (#330031) +- disable -D_FORTIFY_SOURCE{,=2} support (with a warning) for + GCC 3.4.x and earlier(#327641) +- misc fixes (BZ#1140, BZ#3195, BZ#3242, BZ#4359) + * Thu Oct 11 2007 Jakub Jelinek <jakub@redhat.com> 2.6.90-19 - fix <netinet/tcp.h> - simple preprocessor in localedef, fix de_DE collation with it diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c index 343c27521f..ec8f38a962 100644 --- a/iconv/gconv_simple.c +++ b/iconv/gconv_simple.c @@ -1,5 +1,5 @@ /* Simple transformations functions. - Copyright (C) 1997-2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1997-2003, 2004, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -880,7 +880,7 @@ ucs4le_internal_loop_single (struct __gconv_step *step, { \ uint32_t wc = *((const uint32_t *) inptr); \ \ - if (wc < 0x80) \ + if (__builtin_expect (wc < 0x80, 1)) \ /* It's an one byte sequence. */ \ *outptr++ = (unsigned char) wc; \ else if (__builtin_expect (wc <= 0x7fffffff, 1)) \ @@ -940,21 +940,19 @@ ucs4le_internal_loop_single (struct __gconv_step *step, #define LOOPFCT FROM_LOOP #define BODY \ { \ - uint32_t ch; \ - uint_fast32_t cnt; \ - uint_fast32_t i; \ - \ /* Next input byte. */ \ - ch = *inptr; \ + uint32_t ch = *inptr; \ \ - if (ch < 0x80) \ + if (__builtin_expect (ch < 0x80, 1)) \ { \ /* One byte sequence. */ \ - cnt = 1; \ ++inptr; \ } \ else \ { \ + uint_fast32_t cnt; \ + uint_fast32_t i; \ + \ if (ch >= 0xc2 && ch < 0xe0) \ { \ /* We expect two bytes. The first byte cannot be 0xc0 or 0xc1, \ diff --git a/include/features.h b/include/features.h index 0e471875cb..3ab68b67cd 100644 --- a/include/features.h +++ b/include/features.h @@ -282,14 +282,13 @@ #endif #if defined _FORTIFY_SOURCE && _FORTIFY_SOURCE > 0 \ - && defined __OPTIMIZE__ && __OPTIMIZE__ > 0 \ - && (__GNUC_PREREQ (4, 1) \ - || (defined __GNUC_RH_RELEASE__ && __GNUC_PREREQ (4, 0)) \ - || (defined __GNUC_RH_RELEASE__ && __GNUC_PREREQ (3, 4) \ - && __GNUC_MINOR__ == 4 \ - && (__GNUC_PATCHLEVEL__ > 2 \ - || (__GNUC_PATCHLEVEL__ == 2 && __GNUC_RH_RELEASE__ >= 8)))) -# if _FORTIFY_SOURCE > 1 + && defined __OPTIMIZE__ && __OPTIMIZE__ > 0 +# if !__GNUC_PREREQ (4, 1) +# ifdef __GNUC_RH_RELEASE__ +# warning _FORTIFY_SOURCE supported only with GCC 4.1 and later +# endif +# define __USE_FORTIFY_LEVEL 0 +# elif _FORTIFY_SOURCE > 1 # define __USE_FORTIFY_LEVEL 2 # else # define __USE_FORTIFY_LEVEL 1 diff --git a/include/stdio.h b/include/stdio.h index 084c02ea1e..3c11037490 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -138,6 +138,7 @@ libc_hidden_proto (rewind) libc_hidden_proto (fileno) libc_hidden_proto (fwrite) libc_hidden_proto (fseek) +libc_hidden_proto (ftello) libc_hidden_proto (fflush_unlocked) libc_hidden_proto (fread_unlocked) libc_hidden_proto (fwrite_unlocked) diff --git a/include/time.h b/include/time.h index ed6cb3669f..e896406db4 100644 --- a/include/time.h +++ b/include/time.h @@ -46,6 +46,9 @@ extern void __tzfile_compute (time_t timer, int use_localtime, struct tm *tp); extern void __tzfile_default (const char *std, const char *dst, long int stdoff, long int dstoff); +extern void __tzset_parse_tz (const char *tz); +extern void __tz_compute (time_t timer, struct tm *tm, int use_localtime) + __THROW internal_function; /* Subroutine of `mktime'. Return the `time_t' representation of TP and normalize TP, given that a `struct tm *' maps to a `time_t' as performed diff --git a/intl/dcigettext.c b/intl/dcigettext.c index 55dcaabd80..a2cd8014c3 100644 --- a/intl/dcigettext.c +++ b/intl/dcigettext.c @@ -974,6 +974,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp) translation at all. */ if (__builtin_expect (r != __GCONV_NULCONV, 1)) { + __libc_rwlock_unlock (domain->conversions_lock); free ((char *) encoding); return NULL; } diff --git a/libio/Makefile b/libio/Makefile index 553fbda74a..31fac70cfd 100644 --- a/libio/Makefile +++ b/libio/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1995-2002,2003,2004,2006 Free Software Foundation, Inc. +# Copyright (C) 1995-2002,2003,2004,2006,2007 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -48,7 +48,7 @@ routines := \ libc_fatal fmemopen tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ - tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-fopenloc \ + tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 tst-fopenloc \ tst-fgetws tst-ungetwc1 tst-ungetwc2 tst-swscanf tst-sscanf \ tst-mmap-setvbuf bug-ungetwc1 bug-ungetwc2 tst-atime tst-eof \ tst-freopen bug-rewind bug-rewind2 bug-ungetc bug-fseek \ diff --git a/libio/__freading.c b/libio/__freading.c index 37200bba78..43e50bce75 100644 --- a/libio/__freading.c +++ b/libio/__freading.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000, 2002 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2002, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -22,5 +22,6 @@ int __freading (FILE *fp) { return ((fp->_flags & _IO_NO_WRITES) - || (fp->_flags & _IO_CURRENTLY_PUTTING) == 0); + || ((fp->_flags & (_IO_CURRENTLY_PUTTING | _IO_NO_READS)) == 0 + && fp->_IO_read_base != NULL)); } diff --git a/libio/ftello.c b/libio/ftello.c index e58daacad4..d250e55c04 100644 --- a/libio/ftello.c +++ b/libio/ftello.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995-2001, 2002, 2003, 2004 +/* Copyright (C) 1993, 1995-2001, 2002, 2003, 2004, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -63,3 +63,4 @@ ftello (fp) } return pos; } +libc_hidden_def (ftello) diff --git a/libio/tst-ext2.c b/libio/tst-ext2.c new file mode 100644 index 0000000000..ed72efa0c7 --- /dev/null +++ b/libio/tst-ext2.c @@ -0,0 +1,58 @@ +#include <stdio.h> +#include <stdio_ext.h> + + +static char *fname; + +#define PREPARE(argc, argv) \ + do { \ + int fd = create_temp_file ("tst-ext2", &fname); \ + if (fd == -1) \ + { \ + puts ("cannot create temporary file"); \ + exit (1); \ + } \ + close (fd); \ + } while (0) + + +static int +do_test (void) +{ + int res = 0; + + FILE *fp; + + fp = fopen (fname, "w"); + printf ("Initial state for write-only stream: %d %d\n", + __freading (fp) != 0, __fwriting (fp) != 0); + res |= ((__freading (fp) != 0) != 0 + || (__fwriting (fp) != 0) != 1); + fclose (fp); + + fp = fopen (fname, "r"); + printf ("Initial state for read-only stream: %d %d\n", + __freading (fp) != 0, __fwriting (fp) != 0); + res |= ((__freading (fp) != 0) != 1 + || (__fwriting (fp) != 0) != 0); + fclose (fp); + + fp = fopen (fname, "r+"); + printf ("Initial state for read-write stream: %d %d\n", + __freading (fp) != 0, __fwriting (fp) != 0); + res |= ((__freading (fp) != 0) != 0 + || (__fwriting (fp) != 0) != 0); + fclose (fp); + + fp = fopen (fname, "w+"); + printf ("Initial state for read-write stream: %d %d\n", + __freading (fp) != 0, __fwriting (fp) != 0); + res |= ((__freading (fp) != 0) != 0 + || (__fwriting (fp) != 0) != 0); + fclose (fp); + + return res; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c index 6d8f3fb2f0..bf22a2c47b 100644 --- a/locale/programs/ld-collate.c +++ b/locale/programs/ld-collate.c @@ -2662,13 +2662,16 @@ skip_to (struct linereader *ldfile, struct locale_collate_t *collate, if (nowtok == tok_eof || nowtok == tok_end) return nowtok; } - else if ((!to_endif && (nowtok == tok_else || nowtok == tok_elifdef - || nowtok == tok_elifndef)) - || nowtok == tok_endif) + else if (nowtok == tok_endif || (!to_endif && nowtok == tok_else)) { lr_ignore_rest (ldfile, 1); return nowtok; } + else if (!to_endif && (nowtok == tok_elifdef || nowtok == tok_elifndef)) + { + /* Do not read the rest of the line. */ + return nowtok; + } else if (nowtok == tok_else) { lr_error (ldfile, _("%s: more then one 'else'"), "LC_COLLATE"); @@ -2709,43 +2712,38 @@ collate_read (struct linereader *ldfile, struct localedef_t *result, /* The rest of the line containing `LC_COLLATE' must be free. */ lr_ignore_rest (ldfile, 1); - do - { - now = lr_token (ldfile, charmap, result, NULL, verbose); - nowtok = now->tok; - } - while (nowtok == tok_eol); - - while (nowtok == tok_define) + while (1) { - if (ignore_content) + do { - lr_ignore_rest (ldfile, 0); - continue; + now = lr_token (ldfile, charmap, result, NULL, verbose); + nowtok = now->tok; } + while (nowtok == tok_eol); - arg = lr_token (ldfile, charmap, result, NULL, verbose); - if (arg->tok != tok_ident) - SYNTAX_ERROR (_("%s: syntax error"), "LC_COLLATE"); + if (nowtok != tok_define) + break; + + if (ignore_content) + lr_ignore_rest (ldfile, 0); else { - /* Simply add the new symbol. */ - struct name_list *newsym = xmalloc (sizeof (*newsym) - + arg->val.str.lenmb + 1); - memcpy (newsym->str, arg->val.str.startmb, arg->val.str.lenmb); - newsym->str[arg->val.str.lenmb] = '\0'; - newsym->next = defined; - defined = newsym; - - lr_ignore_rest (ldfile, 1); - } + arg = lr_token (ldfile, charmap, result, NULL, verbose); + if (arg->tok != tok_ident) + SYNTAX_ERROR (_("%s: syntax error"), "LC_COLLATE"); + else + { + /* Simply add the new symbol. */ + struct name_list *newsym = xmalloc (sizeof (*newsym) + + arg->val.str.lenmb + 1); + memcpy (newsym->str, arg->val.str.startmb, arg->val.str.lenmb); + newsym->str[arg->val.str.lenmb] = '\0'; + newsym->next = defined; + defined = newsym; - do - { - now = lr_token (ldfile, charmap, result, NULL, verbose); - nowtok = now->tok; + lr_ignore_rest (ldfile, 1); + } } - while (nowtok == tok_eol); } if (nowtok == tok_copy) diff --git a/locale/programs/repertoire.c b/locale/programs/repertoire.c index cc83374c9f..366580e80f 100644 --- a/locale/programs/repertoire.c +++ b/locale/programs/repertoire.c @@ -113,8 +113,7 @@ repertoire_read (const char *filename) filename); repfile = lr_open (buf, repertoiremap_hash); - if (repfile == NULL) - free (buf); + free (buf); } } diff --git a/misc/Makefile b/misc/Makefile index a9709f96db..eb97ac1767 100644 --- a/misc/Makefile +++ b/misc/Makefile @@ -31,7 +31,7 @@ headers := sys/uio.h bits/uio.h sys/ioctl.h bits/ioctls.h bits/ioctl-types.h \ sys/select.h ustat.h sys/ustat.h bits/ustat.h sys/sysinfo.h \ regexp.h bits/select.h bits/mman.h sys/xattr.h \ syslog.h sys/syslog.h \ - bits/syslog.h bits/syslog-ldbl.h bits/syslog-path.h + bits/syslog.h bits/syslog-ldbl.h bits/syslog-path.h bits/error.h routines := brk sbrk sstk ioctl \ readv writev \ diff --git a/nscd/nscd_getai.c b/nscd/nscd_getai.c index 5df32dc6dc..56f963776e 100644 --- a/nscd/nscd_getai.c +++ b/nscd/nscd_getai.c @@ -168,8 +168,8 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop) /* Store the error number. */ *h_errnop = ai_resp.error; - /* The `errno' to some value != ERANGE. */ - __set_errno (ENOENT); + /* Set errno to 0 to indicate no error, just no found record. */ + __set_errno (0); /* Even though we have not found anything, the result is zero. */ retval = 0; } diff --git a/nscd/nscd_getgr_r.c b/nscd/nscd_getgr_r.c index fc036f2888..afb4d20435 100644 --- a/nscd/nscd_getgr_r.c +++ b/nscd/nscd_getgr_r.c @@ -190,26 +190,37 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, /* Read the length information, group name, and password. */ if (gr_name == NULL) { - /* Allocate array to store lengths. */ - if (lensize == 0) + /* Handle a simple, usual case: no group members. */ + if (__builtin_expect (gr_resp.gr_mem_cnt == 0, 1)) { - lensize = gr_resp.gr_mem_cnt * sizeof (uint32_t); - len = (uint32_t *) alloca (lensize); + size_t n = gr_resp.gr_name_len + gr_resp.gr_passwd_len; + if (__builtin_expect (__readall (sock, resultbuf->gr_name, n) + != (ssize_t) n, 0)) + goto out_close; + } + else + { + /* Allocate array to store lengths. */ + if (lensize == 0) + { + lensize = gr_resp.gr_mem_cnt * sizeof (uint32_t); + len = (uint32_t *) alloca (lensize); + } + else if (gr_resp.gr_mem_cnt * sizeof (uint32_t) > lensize) + len = extend_alloca (len, lensize, + gr_resp.gr_mem_cnt * sizeof (uint32_t)); + + vec[0].iov_base = (void *) len; + vec[0].iov_len = gr_resp.gr_mem_cnt * sizeof (uint32_t); + vec[1].iov_base = resultbuf->gr_name; + vec[1].iov_len = gr_resp.gr_name_len + gr_resp.gr_passwd_len; + total_len = vec[0].iov_len + vec[1].iov_len; + + /* Get this data. */ + size_t n = __readvall (sock, vec, 2); + if (__builtin_expect (n != total_len, 0)) + goto out_close; } - else if (gr_resp.gr_mem_cnt * sizeof (uint32_t) > lensize) - len = extend_alloca (len, lensize, - gr_resp.gr_mem_cnt * sizeof (uint32_t)); - - vec[0].iov_base = (void *) len; - vec[0].iov_len = gr_resp.gr_mem_cnt * sizeof (uint32_t); - vec[1].iov_base = resultbuf->gr_name; - vec[1].iov_len = gr_resp.gr_name_len + gr_resp.gr_passwd_len; - total_len = vec[0].iov_len + vec[1].iov_len; - - /* Get this data. */ - size_t n = __readvall (sock, vec, 2); - if (__builtin_expect (n != total_len, 0)) - goto out_close; } else /* We already have the data. Just copy the group name and @@ -251,17 +262,22 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, } retval = 0; + + /* If there are no group members TOTAL_LEN is zero. */ if (gr_name == NULL) { - size_t n = __readall (sock, resultbuf->gr_mem[0], total_len); - if (__builtin_expect (n != total_len, 0)) + if (total_len > 0) { - /* The `errno' to some value != ERANGE. */ - __set_errno (ENOENT); - retval = ENOENT; + size_t n = __readall (sock, resultbuf->gr_mem[0], total_len); + if (__builtin_expect (n != total_len, 0)) + { + /* The `errno' to some value != ERANGE. */ + __set_errno (ENOENT); + retval = ENOENT; + } + else + *result = resultbuf; } - else - *result = resultbuf; } else { @@ -272,9 +288,9 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, if (resultbuf->gr_name[gr_name_len - 1] != '\0' || resultbuf->gr_passwd[gr_resp.gr_passwd_len - 1] != '\0' || ({for (cnt = 0; cnt < gr_resp.gr_mem_cnt; ++cnt) - if (resultbuf->gr_mem[cnt][len[cnt] - 1] != '\0') - break; - cnt < gr_resp.gr_mem_cnt; })) + if (resultbuf->gr_mem[cnt][len[cnt] - 1] != '\0') + break; + cnt < gr_resp.gr_mem_cnt; })) { /* We cannot use the database. */ retval = mapped->head->gc_cycle != gc_cycle ? -2 : -1; @@ -286,8 +302,8 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, } else { - /* The `errno' to some value != ERANGE. */ - __set_errno (ENOENT); + /* Set errno to 0 to indicate no error, just no found record. */ + __set_errno (0); /* Even though we have not found anything, the result is zero. */ retval = 0; } diff --git a/nscd/nscd_gethst_r.c b/nscd/nscd_gethst_r.c index 03b73a4a47..a211404756 100644 --- a/nscd/nscd_gethst_r.c +++ b/nscd/nscd_gethst_r.c @@ -379,8 +379,8 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, /* Store the error number. */ *h_errnop = hst_resp.error; - /* The `errno' to some value != ERANGE. */ - __set_errno (ENOENT); + /* Set errno to 0 to indicate no error, just no found record. */ + __set_errno (0); /* Even though we have not found anything, the result is zero. */ retval = 0; } diff --git a/nscd/nscd_getpw_r.c b/nscd/nscd_getpw_r.c index b84baa1a66..21f792bb4e 100644 --- a/nscd/nscd_getpw_r.c +++ b/nscd/nscd_getpw_r.c @@ -211,8 +211,8 @@ nscd_getpw_r (const char *key, size_t keylen, request_type type, } else { - /* The `errno' to some value != ERANGE. */ - __set_errno (ENOENT); + /* Set errno to 0 to indicate no error, just no found record. */ + __set_errno (0); /* Even though we have not found anything, the result is zero. */ retval = 0; } diff --git a/nscd/nscd_getserv_r.c b/nscd/nscd_getserv_r.c index a725b1d3de..3cd5a24298 100644 --- a/nscd/nscd_getserv_r.c +++ b/nscd/nscd_getserv_r.c @@ -301,8 +301,8 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto, } else { - /* The `errno' to some value != ERANGE. */ - __set_errno (ENOENT); + /* Set errno to 0 to indicate no error, just no found record. */ + __set_errno (0); /* Even though we have not found anything, the result is zero. */ retval = 0; } diff --git a/nscd/nscd_helper.c b/nscd/nscd_helper.c index 6718d922f3..866535200f 100644 --- a/nscd/nscd_helper.c +++ b/nscd/nscd_helper.c @@ -38,6 +38,45 @@ #include "nscd-client.h" +/* Extra time we wait if the socket is still receiving data. This + value is in milliseconds. Note that the other side is nscd on the + local machine and it is already transmitting data. So the wait + time need not be long. */ +#define EXTRA_RECEIVE_TIME 200 + + +static int +wait_on_socket (int sock, long int usectmo) +{ + struct pollfd fds[1]; + fds[0].fd = sock; + fds[0].events = POLLIN | POLLERR | POLLHUP; + int n = __poll (fds, 1, usectmo); + if (n == -1 && __builtin_expect (errno == EINTR, 0)) + { + /* Handle the case where the poll() call is interrupted by a + signal. We cannot just use TEMP_FAILURE_RETRY since it might + lead to infinite loops. */ + struct timeval now; + (void) __gettimeofday (&now, NULL); + long int end = now.tv_sec * 1000 + usectmo + (now.tv_usec + 500) / 1000; + long int timeout = usectmo; + while (1) + { + n = __poll (fds, 1, timeout); + if (n != -1 || errno != EINTR) + break; + + /* Recompute the timeout time. */ + (void) __gettimeofday (&now, NULL); + timeout = end - (now.tv_sec * 1000 + (now.tv_usec + 500) / 1000); + } + } + + return n; +} + + ssize_t __readall (int fd, void *buf, size_t len) { @@ -45,9 +84,17 @@ __readall (int fd, void *buf, size_t len) ssize_t ret; do { + again: ret = TEMP_FAILURE_RETRY (__read (fd, buf, n)); if (ret <= 0) - break; + { + if (__builtin_expect (ret < 0 && errno == EAGAIN, 0) + /* The socket is still receiving data. Wait a bit more. */ + && wait_on_socket (fd, EXTRA_RECEIVE_TIME) > 0) + goto again; + + break; + } buf = (char *) buf + ret; n -= ret; } @@ -61,7 +108,15 @@ __readvall (int fd, const struct iovec *iov, int iovcnt) { ssize_t ret = TEMP_FAILURE_RETRY (__readv (fd, iov, iovcnt)); if (ret <= 0) - return ret; + { + if (__builtin_expect (ret == 0 || errno != EAGAIN, 1)) + /* A genuine error or no data to read. */ + return ret; + + /* The data has not all yet been received. Do as if we have not + read anything yet. */ + ret = 0; + } size_t total = 0; for (int i = 0; i < iovcnt; ++i) @@ -83,9 +138,17 @@ __readvall (int fd, const struct iovec *iov, int iovcnt) } iovp->iov_base = (char *) iovp->iov_base + r; iovp->iov_len -= r; + again: r = TEMP_FAILURE_RETRY (__readv (fd, iovp, iovcnt)); if (r <= 0) - break; + { + if (__builtin_expect (r < 0 && errno == EAGAIN, 0) + /* The socket is still receiving data. Wait a bit more. */ + && wait_on_socket (fd, EXTRA_RECEIVE_TIME) > 0) + goto again; + + break; + } ret += r; } while (ret < total); @@ -187,36 +250,6 @@ __nscd_unmap (struct mapped_database *mapped) } -static int -wait_on_socket (int sock) -{ - struct pollfd fds[1]; - fds[0].fd = sock; - fds[0].events = POLLIN | POLLERR | POLLHUP; - int n = __poll (fds, 1, 5 * 1000); - if (n == -1 && __builtin_expect (errno == EINTR, 0)) - { - /* Handle the case where the poll() call is interrupted by a - signal. We cannot just use TEMP_FAILURE_RETRY since it might - lead to infinite loops. */ - struct timeval now; - (void) __gettimeofday (&now, NULL); - long int end = (now.tv_sec + 5) * 1000 + (now.tv_usec + 500) / 1000; - while (1) - { - long int timeout = end - (now.tv_sec * 1000 - + (now.tv_usec + 500) / 1000); - n = __poll (fds, 1, timeout); - if (n != -1 || errno != EINTR) - break; - (void) __gettimeofday (&now, NULL); - } - } - - return n; -} - - /* Try to get a file descriptor for the shared meory segment containing the database. */ static struct mapped_database * @@ -265,7 +298,7 @@ get_mapping (request_type type, const char *key, msg.msg_controllen = cmsg->cmsg_len; - if (wait_on_socket (sock) <= 0) + if (wait_on_socket (sock, 5 * 1000) <= 0) goto out_close2; # ifndef MSG_CMSG_CLOEXEC @@ -497,7 +530,7 @@ __nscd_open_socket (const char *key, size_t keylen, request_type type, if (sock >= 0) { /* Wait for data. */ - if (wait_on_socket (sock) > 0) + if (wait_on_socket (sock, 5 * 1000) > 0) { ssize_t nbytes = TEMP_FAILURE_RETRY (__read (sock, response, responselen)); diff --git a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c index 2bdd837184..67c0ee4abb 100644 --- a/posix/fnmatch_loop.c +++ b/posix/fnmatch_loop.c @@ -1,5 +1,5 @@ -/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2003,2004,2005, - 2007 Free Software Foundation, Inc. +/* Copyright (C) 1991-1993,1996-2001,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 @@ -418,15 +418,20 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends) /* We found a table entry. Now see whether the character we are currently at has the same equivalance class value. */ - int len = weights[idx]; + int len = weights[idx & 0xffffff]; int32_t idx2; const UCHAR *np = (const UCHAR *) n; idx2 = findidx (&np); - if (idx2 != 0 && len == weights[idx2]) + if (idx2 != 0 + && (idx >> 24) == (idx2 >> 24) + && len == weights[idx2 & 0xffffff]) { int cnt = 0; + idx &= 0xffffff; + idx2 &= 0xffffff; + while (cnt < len && (weights[idx + 1 + cnt] == weights[idx2 + 1 + cnt])) diff --git a/posix/regcomp.c b/posix/regcomp.c index 129546c32c..4cf168821c 100644 --- a/posix/regcomp.c +++ b/posix/regcomp.c @@ -3378,7 +3378,7 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name) /* Build single byte matcing table for this equivalence class. */ char_buf[1] = (unsigned char) '\0'; - len = weights[idx1]; + len = weights[idx1 & 0xffffff]; for (ch = 0; ch < SBC_MAX; ++ch) { char_buf[0] = ch; @@ -3390,11 +3390,15 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name) if (idx2 == 0) /* This isn't a valid character. */ continue; - if (len == weights[idx2]) + /* Compare only if the length matches and the collation rule + index is the same. */ + if (len == weights[idx2 & 0xffffff] && (idx1 >> 24) == (idx2 >> 24)) { int cnt = 0; + while (cnt <= len && - weights[idx1 + 1 + cnt] == weights[idx2 + 1 + cnt]) + weights[(idx1 & 0xffffff) + 1 + cnt] + == weights[(idx2 & 0xffffff) + 1 + cnt]) ++cnt; if (cnt > len) diff --git a/posix/regexec.c b/posix/regexec.c index bdfa3550a7..135efe7441 100644 --- a/posix/regexec.c +++ b/posix/regexec.c @@ -1,5 +1,5 @@ /* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>. @@ -3825,7 +3825,6 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, const int32_t *table, *indirect; const unsigned char *weights, *extra; const char *collseqwc; - int32_t idx; /* This #include defines a local function! */ # include <locale/weight.h> @@ -3883,15 +3882,20 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); - idx = findidx (&cp); + int32_t idx = findidx (&cp); if (idx > 0) for (i = 0; i < cset->nequiv_classes; ++i) { int32_t equiv_class_idx = cset->equiv_classes[i]; - size_t weight_len = weights[idx]; - if (weight_len == weights[equiv_class_idx]) + size_t weight_len = weights[idx & 0xffffff]; + if (weight_len == weights[equiv_class_idx & 0xffffff] + && (idx >> 24) == (equiv_class_idx >> 24)) { int cnt = 0; + + idx &= 0xffffff; + equiv_class_idx &= 0xffffff; + while (cnt <= weight_len && (weights[equiv_class_idx + 1 + cnt] == weights[idx + 1 + cnt])) diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c index 221b41dd00..8f37ec5c11 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c @@ -1002,6 +1002,7 @@ struct sort_result { struct addrinfo *dest_addr; struct sockaddr_storage source_addr; + size_t service_order; uint8_t source_addr_len; bool got_source_addr; uint8_t source_addr_flags; @@ -1403,8 +1404,11 @@ rfc3484_sort (const void *p1, const void *p2) } - /* Rule 10: Otherwise, leave the order unchanged. */ - return 0; + /* Rule 10: Otherwise, leave the order unchanged. To ensure this + compare with the value indicating the order in which the entries + have been received from the services. NB: no two entries can have + the same order so the test will never return zero. */ + return a1->service_order < a2->service_order ? -1 : 1; } @@ -1951,6 +1955,7 @@ getaddrinfo (const char *name, const char *service, { results[i].dest_addr = q; results[i].got_source_addr = false; + results[i].service_order = i; /* If we just looked up the address for a different protocol, reuse the result. */ diff --git a/time/tzfile.c b/time/tzfile.c index 0d48c8ca0c..44d6614771 100644 --- a/time/tzfile.c +++ b/time/tzfile.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-1993,1995-2001,2003,2004,2006 +/* Copyright (C) 1991-1993,1995-2001,2003,2004,2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -50,7 +50,6 @@ struct leap long int change; /* Seconds of correction to apply. */ }; -static struct ttinfo *find_transition (time_t timer) internal_function; static void compute_tzname_max (size_t) internal_function; static size_t num_transitions; @@ -63,6 +62,7 @@ static long int rule_stdoff; static long int rule_dstoff; static size_t num_leaps; static struct leap *leaps; +static char *tzspec; #include <endian.h> #include <byteswap.h> @@ -114,6 +114,7 @@ __tzfile_read (const char *file, size_t extra, char **extrap) size_t leaps_idx; int was_using_tzfile = __use_tzfile; int trans_width = 4; + size_t tzspec_len; if (sizeof (time_t) != 4 && sizeof (time_t) != 8) abort (); @@ -242,10 +243,18 @@ __tzfile_read (const char *file, size_t extra, char **extrap) & ~(__alignof__ (struct leap) - 1)); leaps_idx = total_size; total_size += num_leaps * sizeof (struct leap); + tzspec_len = (trans_width == 8 + ? st.st_size - (ftello (f) + + num_transitions * (8 + 1) + + num_types * 6 + + chars + + num_leaps * 8 + + num_isstd + + num_isgmt) - 1 : 0); /* Allocate enough memory including the extra block requested by the caller. */ - transitions = (time_t *) malloc (total_size + extra); + transitions = (time_t *) malloc (total_size + tzspec_len + extra); if (transitions == NULL) goto lose; @@ -254,6 +263,10 @@ __tzfile_read (const char *file, size_t extra, char **extrap) types = (struct ttinfo *) ((char *) transitions + types_idx); zone_names = (char *) types + num_types * sizeof (struct ttinfo); leaps = (struct leap *) ((char *) transitions + leaps_idx); + if (trans_width == 8) + tzspec = (char *) leaps + num_leaps * sizeof (struct leap); + else + tzspec = NULL; if (extra > 0) *extrap = (char *) &leaps[num_leaps]; @@ -357,11 +370,16 @@ __tzfile_read (const char *file, size_t extra, char **extrap) while (i < num_types) types[i++].isgmt = 0; - /* XXX When a version 2 file is available it can contain a POSIX TZ-style - formatted string which specifies how times past the last one specified - are supposed to be handled. We might want to handle this at some - point. But it might be overhead since most/all? files have an - open-ended last entry. */ + /* Read the POSIX TZ-style information if possible. */ + if (tzspec != NULL) + { + /* Skip over the newline first. */ + if (getc_unlocked (f) != '\n' + || fread_unlocked (tzspec, 1, tzspec_len - 1, f) != tzspec_len - 1) + tzspec = NULL; + else + tzspec[tzspec_len - 1] = '\0'; + } fclose (f); @@ -531,111 +549,151 @@ __tzfile_default (const char *std, const char *dst, compute_tzname_max (stdlen + dstlen); } -static struct ttinfo * -internal_function -find_transition (time_t timer) +void +__tzfile_compute (time_t timer, int use_localtime, + long int *leap_correct, int *leap_hit, + struct tm *tp) { - size_t i; + register size_t i; - if (num_transitions == 0 || timer < transitions[0]) - { - /* TIMER is before any transition (or there are no transitions). - Choose the first non-DST type - (or the first if they're all DST types). */ - i = 0; - while (i < num_types && types[i].isdst) - ++i; - if (i == num_types) - i = 0; - } - else if (timer >= transitions[num_transitions - 1]) - i = type_idxs[num_transitions - 1]; - else + if (use_localtime) { - /* Find the first transition after TIMER, and - then pick the type of the transition before it. */ - size_t lo = 0; - size_t hi = num_transitions - 1; - /* Assume that DST is changing twice a year and guess initial - search spot from it. - Half of a gregorian year has on average 365.2425 * 86400 / 2 - = 15778476 seconds. */ - i = (transitions[num_transitions - 1] - timer) / 15778476; - if (i < num_transitions) + __tzname[0] = NULL; + __tzname[1] = NULL; + + if (num_transitions == 0 || timer < transitions[0]) { - i = num_transitions - 1 - i; - if (timer < transitions[i]) + /* TIMER is before any transition (or there are no transitions). + Choose the first non-DST type + (or the first if they're all DST types). */ + i = 0; + while (i < num_types && types[i].isdst) { - if (i < 10 || timer >= transitions[i - 10]) - { - /* Linear search. */ - while (timer < transitions[i - 1]) - --i; - goto found; - } - hi = i - 10; + if (__tzname[1] == NULL) + __tzname[1] = __tzstring (&zone_names[types[i].idx]); + + ++i; } - else + + if (i == num_types) + i = 0; + __tzname[0] = __tzstring (&zone_names[types[i].idx]); + if (__tzname[1] == NULL) { - if (i + 10 >= num_transitions || timer < transitions[i + 10]) - { - /* Linear search. */ - while (timer >= transitions[i]) - ++i; - goto found; - } - lo = i + 10; + size_t j = i; + while (j < num_types) + if (types[j].isdst) + { + __tzname[1] = __tzstring (&zone_names[types[j].idx]); + break; + } + else + ++j; } } - - /* Binary search. */ - /* assert (timer >= transitions[lo] && timer < transitions[hi]); */ - while (lo + 1 < hi) + else if (timer >= transitions[num_transitions - 1]) { - i = (lo + hi) / 2; - if (timer < transitions[i]) - hi = i; - else - lo = i; - } - i = hi; + if (tzspec == NULL) + { + use_last: + i = num_transitions - 1; + goto found; + } - found: - /* assert (timer >= transitions[i - 1] && timer < transitions[i]); */ - i = type_idxs[i - 1]; - } + /* Parse the POSIX TZ-style string. */ + __tzset_parse_tz (tzspec); - return &types[i]; -} - -void -__tzfile_compute (time_t timer, int use_localtime, - long int *leap_correct, int *leap_hit, - struct tm *tp) -{ - register size_t i; + /* Convert to broken down structure. If this fails do not + use the string. */ + if (! __offtime (&timer, 0, tp)) + goto use_last; - if (use_localtime) - { - struct ttinfo *info = find_transition (timer); - __daylight = rule_stdoff != rule_dstoff; - __timezone = -rule_stdoff; - __tzname[0] = NULL; - __tzname[1] = NULL; - for (i = num_transitions; i > 0; ) + /* Use the rules from the TZ string to compute the change. */ + __tz_compute (timer, tp, 1); + + *leap_correct = 0L; + *leap_hit = 0; + return; + } + else { - int type = type_idxs[--i]; - int dst = types[type].isdst; - int idx = types[type].idx; + /* Find the first transition after TIMER, and + then pick the type of the transition before it. */ + size_t lo = 0; + size_t hi = num_transitions - 1; + /* Assume that DST is changing twice a year and guess initial + search spot from it. + Half of a gregorian year has on average 365.2425 * 86400 / 2 + = 15778476 seconds. */ + i = (transitions[num_transitions - 1] - timer) / 15778476; + if (i < num_transitions) + { + i = num_transitions - 1 - i; + if (timer < transitions[i]) + { + if (i < 10 || timer >= transitions[i - 10]) + { + /* Linear search. */ + while (timer < transitions[i - 1]) + --i; + goto found; + } + hi = i - 10; + } + else + { + if (i + 10 >= num_transitions || timer < transitions[i + 10]) + { + /* Linear search. */ + while (timer >= transitions[i]) + ++i; + goto found; + } + lo = i + 10; + } + } - if (__tzname[dst] == NULL) + /* Binary search. */ + /* assert (timer >= transitions[lo] && timer < transitions[hi]); */ + while (lo + 1 < hi) + { + i = (lo + hi) / 2; + if (timer < transitions[i]) + hi = i; + else + lo = i; + } + i = hi; + + found: + /* assert (timer >= transitions[i - 1] && timer < transitions[i]); */ + __tzname[types[type_idxs[i - 1]].isdst] + = __tzstring (&zone_names[types[type_idxs[i - 1]].idx]); + size_t j = i; + while (j < num_transitions) { - __tzname[dst] = __tzstring (&zone_names[idx]); + int type = type_idxs[j]; + int dst = types[type].isdst; + int idx = types[type].idx; + + if (__tzname[dst] == NULL) + { + __tzname[dst] = __tzstring (&zone_names[idx]); + + if (__tzname[1 - dst] != NULL) + break; + } - if (__tzname[1 - dst] != NULL) - break; + ++j; } + + i = type_idxs[i - 1]; } + + struct ttinfo *info = &types[i]; + __daylight = rule_stdoff != rule_dstoff; + __timezone = -rule_stdoff; + if (__tzname[0] == NULL) { /* This should only happen if there are no transition rules. @@ -647,7 +705,8 @@ __tzfile_compute (time_t timer, int use_localtime, /* There is no daylight saving time. */ __tzname[1] = __tzname[0]; tp->tm_isdst = info->isdst; - tp->tm_zone = __tzstring (&zone_names[info->idx]); + assert (strcmp (&zone_names[info->idx], __tzname[tp->tm_isdst]) == 0); + tp->tm_zone = __tzname[tp->tm_isdst]; tp->tm_gmtoff = info->offset; } diff --git a/time/tzset.c b/time/tzset.c index 0479abb38a..27efef0f7a 100644 --- a/time/tzset.c +++ b/time/tzset.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2002,2003,2004 Free Software Foundation, Inc. +/* Copyright (C) 1991-2002,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 @@ -70,7 +70,6 @@ static tz_rule tz_rules[2]; static void compute_change (tz_rule *rule, int year) __THROW internal_function; -static void tz_compute (const struct tm *tm) __THROW internal_function; static void tzset_internal (int always, int explicit) __THROW internal_function; @@ -92,7 +91,7 @@ __tzstring (const char *s) { char *p; struct tzstring_l *t, *u, *new; - size_t len = strlen(s); + size_t len = strlen (s); /* Walk the list and look for a match. If this string is the same as the end of an already-allocated string, it can share space. */ @@ -140,80 +139,34 @@ __tzname_max () static char *old_tz; -/* Interpret the TZ envariable. */ static void internal_function -tzset_internal (always, explicit) - int always; - int explicit; +update_vars (void) +{ + __daylight = tz_rules[0].offset != tz_rules[1].offset; + __timezone = -tz_rules[0].offset; + __tzname[0] = (char *) tz_rules[0].name; + __tzname[1] = (char *) tz_rules[1].name; + + /* Keep __tzname_cur_max up to date. */ + size_t len0 = strlen (__tzname[0]); + size_t len1 = strlen (__tzname[1]); + if (len0 > __tzname_cur_max) + __tzname_cur_max = len0; + if (len1 > __tzname_cur_max) + __tzname_cur_max = len1; +} + +/* Parse the POSIX TZ-style string. */ +void +__tzset_parse_tz (tz) + const char *tz; { - static int is_initialized; - register const char *tz; register size_t l; char *tzbuf; unsigned short int hh, mm, ss; unsigned short int whichrule; - if (is_initialized && !always) - return; - is_initialized = 1; - - /* Examine the TZ environment variable. */ - tz = getenv ("TZ"); - if (tz == NULL && !explicit) - /* Use the site-wide default. This is a file name which means we - would not see changes to the file if we compare only the file - name for change. We want to notice file changes if tzset() has - been called explicitly. Leave TZ as NULL in this case. */ - tz = TZDEFAULT; - if (tz && *tz == '\0') - /* User specified the empty string; use UTC explicitly. */ - tz = "Universal"; - - /* A leading colon means "implementation defined syntax". - We ignore the colon and always use the same algorithm: - try a data file, and if none exists parse the 1003.1 syntax. */ - if (tz && *tz == ':') - ++tz; - - /* Check whether the value changes since the last run. */ - if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0) - /* No change, simply return. */ - return; - - if (tz == NULL) - /* No user specification; use the site-wide default. */ - tz = TZDEFAULT; - - tz_rules[0].name = NULL; - tz_rules[1].name = NULL; - - /* Save the value of `tz'. */ - if (old_tz != NULL) - free (old_tz); - old_tz = tz ? __strdup (tz) : NULL; - - /* Try to read a data file. */ - __tzfile_read (tz, 0, NULL); - if (__use_tzfile) - return; - - /* No data file found. Default to UTC if nothing specified. */ - - if (tz == NULL || *tz == '\0' - || (TZDEFAULT != NULL && strcmp (tz, TZDEFAULT) == 0)) - { - tz_rules[0].name = tz_rules[1].name = "UTC"; - tz_rules[0].type = tz_rules[1].type = J0; - tz_rules[0].m = tz_rules[0].n = tz_rules[0].d = 0; - tz_rules[1].m = tz_rules[1].n = tz_rules[1].d = 0; - tz_rules[0].secs = tz_rules[1].secs = 0; - tz_rules[0].offset = tz_rules[1].offset = 0L; - tz_rules[0].change = tz_rules[1].change = (time_t) -1; - tz_rules[0].computed_for = tz_rules[1].computed_for = 0; - goto out; - } - /* Clear out old state and reset to unnamed UTC. */ memset (tz_rules, 0, sizeof tz_rules); tz_rules[0].name = tz_rules[1].name = ""; @@ -413,20 +366,81 @@ tzset_internal (always, explicit) } out: - __daylight = tz_rules[0].offset != tz_rules[1].offset; - __timezone = -tz_rules[0].offset; - __tzname[0] = (char *) tz_rules[0].name; - __tzname[1] = (char *) tz_rules[1].name; + update_vars (); +} - { - /* Keep __tzname_cur_max up to date. */ - size_t len0 = strlen (__tzname[0]); - size_t len1 = strlen (__tzname[1]); - if (len0 > __tzname_cur_max) - __tzname_cur_max = len0; - if (len1 > __tzname_cur_max) - __tzname_cur_max = len1; - } +/* Interpret the TZ envariable. */ +static void +internal_function +tzset_internal (always, explicit) + int always; + int explicit; +{ + static int is_initialized; + register const char *tz; + + if (is_initialized && !always) + return; + is_initialized = 1; + + /* Examine the TZ environment variable. */ + tz = getenv ("TZ"); + if (tz == NULL && !explicit) + /* Use the site-wide default. This is a file name which means we + would not see changes to the file if we compare only the file + name for change. We want to notice file changes if tzset() has + been called explicitly. Leave TZ as NULL in this case. */ + tz = TZDEFAULT; + if (tz && *tz == '\0') + /* User specified the empty string; use UTC explicitly. */ + tz = "Universal"; + + /* A leading colon means "implementation defined syntax". + We ignore the colon and always use the same algorithm: + try a data file, and if none exists parse the 1003.1 syntax. */ + if (tz && *tz == ':') + ++tz; + + /* Check whether the value changes since the last run. */ + if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0) + /* No change, simply return. */ + return; + + if (tz == NULL) + /* No user specification; use the site-wide default. */ + tz = TZDEFAULT; + + tz_rules[0].name = NULL; + tz_rules[1].name = NULL; + + /* Save the value of `tz'. */ + if (old_tz != NULL) + free (old_tz); + old_tz = tz ? __strdup (tz) : NULL; + + /* Try to read a data file. */ + __tzfile_read (tz, 0, NULL); + if (__use_tzfile) + return; + + /* No data file found. Default to UTC if nothing specified. */ + + if (tz == NULL || *tz == '\0' + || (TZDEFAULT != NULL && strcmp (tz, TZDEFAULT) == 0)) + { + tz_rules[0].name = tz_rules[1].name = "UTC"; + tz_rules[0].type = tz_rules[1].type = J0; + tz_rules[0].m = tz_rules[0].n = tz_rules[0].d = 0; + tz_rules[1].m = tz_rules[1].n = tz_rules[1].d = 0; + tz_rules[0].secs = tz_rules[1].secs = 0; + tz_rules[0].offset = tz_rules[1].offset = 0L; + tz_rules[0].change = tz_rules[1].change = (time_t) -1; + tz_rules[0].computed_for = tz_rules[1].computed_for = 0; + update_vars (); + return; + } + + __tzset_parse_tz (tz); } /* Figure out the exact time (as a time_t) in YEAR @@ -523,13 +537,34 @@ compute_change (rule, year) /* Figure out the correct timezone for TM and set `__tzname', `__timezone', and `__daylight' accordingly. */ -static void +void internal_function -tz_compute (tm) - const struct tm *tm; +__tz_compute (timer, tm, use_localtime) + time_t timer; + struct tm *tm; + int use_localtime; { compute_change (&tz_rules[0], 1900 + tm->tm_year); compute_change (&tz_rules[1], 1900 + tm->tm_year); + + if (use_localtime) + { + int isdst; + + /* We have to distinguish between northern and southern + hemisphere. For the latter the daylight saving time + ends in the next year. */ + if (__builtin_expect (tz_rules[0].change + > tz_rules[1].change, 0)) + isdst = (timer < tz_rules[1].change + || timer >= tz_rules[0].change); + else + isdst = (timer >= tz_rules[0].change + && timer < tz_rules[1].change); + tm->tm_isdst = isdst; + tm->tm_zone = __tzname[isdst]; + tm->tm_gmtoff = tz_rules[isdst].offset; + } } /* Reinterpret the TZ environment variable and set `tzname'. */ @@ -583,35 +618,14 @@ __tz_convert (const time_t *timer, int use_localtime, struct tm *tp) if (! __offtime (timer, 0, tp)) tp = NULL; else - tz_compute (tp); + __tz_compute (*timer, tp, use_localtime); leap_correction = 0L; leap_extra_secs = 0; } if (tp) { - if (use_localtime) - { - if (!__use_tzfile) - { - int isdst; - - /* We have to distinguish between northern and southern - hemisphere. For the latter the daylight saving time - ends in the next year. */ - if (__builtin_expect (tz_rules[0].change - > tz_rules[1].change, 0)) - isdst = (*timer < tz_rules[1].change - || *timer >= tz_rules[0].change); - else - isdst = (*timer >= tz_rules[0].change - && *timer < tz_rules[1].change); - tp->tm_isdst = isdst; - tp->tm_zone = __tzname[isdst]; - tp->tm_gmtoff = tz_rules[isdst].offset; - } - } - else + if (! use_localtime) { tp->tm_isdst = 0; tp->tm_zone = "GMT"; diff --git a/timezone/tst-timezone.c b/timezone/tst-timezone.c index 4c879163cf..00f899b851 100644 --- a/timezone/tst-timezone.c +++ b/timezone/tst-timezone.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 1999, 2000, 2005 Free Software Foundation, Inc. +/* Copyright (C) 1998, 1999, 2000, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Jaeger <aj@suse.de>, 1998. @@ -44,7 +44,6 @@ static const struct test_times tests[] = { "America/Chicago", 1, 21600, {"CST", "CDT" }}, { "America/Indiana/Indianapolis", 1, 18000, {"EST", "EDT" }}, { "America/Los_Angeles", 1, 28800, {"PST", "PDT" }}, - { "Asia/Tokyo", 1, -32400, {"JST", "JDT" }}, { "Pacific/Auckland", 1, -43200, { "NZST", "NZDT" }}, { NULL, 0, 0 } }; |