X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=lib%2Ferror.c;h=adc873391cb49e164297fd1d9f16ca0aedcf1e60;hb=659cae49714b93487242525dfa0e5737463d78d8;hp=cf8634332020392497c23a438eef02aaaa0c71eb;hpb=0d5a754ba8f2cc33e98d48d559f0ad6cd18a43a3;p=debian%2Fgzip diff --git a/lib/error.c b/lib/error.c index cf86343..adc8733 100644 --- a/lib/error.c +++ b/lib/error.c @@ -1,20 +1,19 @@ /* Error handler for noninteractive utilities - Copyright (C) 1990-1998, 2000-2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1990-1998, 2000-2007, 2009-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ /* Written by David MacKenzie . */ @@ -31,6 +30,7 @@ #if !_LIBC && ENABLE_NLS # include "gettext.h" +# define _(msgid) gettext (msgid) #endif #ifdef _LIBC @@ -39,6 +39,11 @@ # include # include # define mbsrtowcs __mbsrtowcs +# define USE_UNLOCKED_IO 0 +# define _GL_ATTRIBUTE_FORMAT_PRINTF(a, b) +# define _GL_ARG_NONNULL(a) +#else +# include "getprogname.h" #endif #if USE_UNLOCKED_IO @@ -54,7 +59,7 @@ function without parameters instead. */ void (*error_print_progname) (void); -/* This variable is incremented each time `error' is called. */ +/* This variable is incremented each time 'error' is called. */ unsigned int error_message_count; #ifdef _LIBC @@ -65,50 +70,115 @@ unsigned int error_message_count; # include # include -/* In GNU libc we want do not want to use the common name `error' directly. +/* In GNU libc we want do not want to use the common name 'error' directly. Instead make it a weak alias. */ extern void __error (int status, int errnum, const char *message, ...) __attribute__ ((__format__ (__printf__, 3, 4))); extern void __error_at_line (int status, int errnum, const char *file_name, - unsigned int line_number, const char *message, - ...) - __attribute__ ((__format__ (__printf__, 5, 6)));; + unsigned int line_number, const char *message, + ...) + __attribute__ ((__format__ (__printf__, 5, 6))); # define error __error # define error_at_line __error_at_line # include -# define fflush(s) INTUSE(_IO_fflush) (s) +# define fflush(s) _IO_fflush (s) # undef putc -# define putc(c, fp) INTUSE(_IO_putc) (c, fp) +# define putc(c, fp) _IO_putc (c, fp) # include #else /* not _LIBC */ -# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P +# include +# include + +# if defined _WIN32 && ! defined __CYGWIN__ +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include +/* Get _get_osfhandle. */ +# if GNULIB_MSVC_NOTHROW +# include "msvc-nothrow.h" +# else +# include +# endif +# endif + +/* The gnulib override of fcntl is not needed in this file. */ +# undef fcntl + +# if !(GNULIB_STRERROR_R_POSIX || HAVE_DECL_STRERROR_R) # ifndef HAVE_DECL_STRERROR_R "this configure-time declaration test was not run" # endif -char *strerror_r (); +# if STRERROR_R_CHAR_P +char *strerror_r (int errnum, char *buf, size_t buflen); +# else +int strerror_r (int errnum, char *buf, size_t buflen); +# endif # endif -/* The calling program should define program_name and set it to the - name of the executing program. */ -extern char *program_name; +#define program_name getprogname () -# if HAVE_STRERROR_R || defined strerror_r +# if GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r # define __strerror_r strerror_r -# endif /* HAVE_STRERROR_R || defined strerror_r */ -#endif /* not _LIBC */ +# endif /* GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r */ +#endif /* not _LIBC */ + +#if !_LIBC +/* Return non-zero if FD is open. */ +static int +is_open (int fd) +{ +# if defined _WIN32 && ! defined __CYGWIN__ + /* On native Windows: The initial state of unassigned standard file + descriptors is that they are open but point to an INVALID_HANDLE_VALUE. + There is no fcntl, and the gnulib replacement fcntl does not support + F_GETFL. */ + return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE; +# else +# ifndef F_GETFL +# error Please port fcntl to your platform +# endif + return 0 <= fcntl (fd, F_GETFL); +# endif +} +#endif + +static void +flush_stdout (void) +{ +#if !_LIBC + int stdout_fd; + +# if GNULIB_FREOPEN_SAFER + /* Use of gnulib's freopen-safer module normally ensures that + fileno (stdout) == 1 + whenever stdout is open. */ + stdout_fd = STDOUT_FILENO; +# else + /* POSIX states that fileno (stdout) after fclose is unspecified. But in + practice it is not a problem, because stdout is statically allocated and + the fd of a FILE stream is stored as a field in its allocated memory. */ + stdout_fd = fileno (stdout); +# endif + /* POSIX states that fflush (stdout) after fclose is unspecified; it + is safe in glibc, but not on all other platforms. fflush (NULL) + is always defined, but too draconian. */ + if (0 <= stdout_fd && is_open (stdout_fd)) +#endif + fflush (stdout); +} static void print_errno_message (int errnum) { char const *s; -#if defined HAVE_STRERROR_R || _LIBC +#if _LIBC || GNULIB_STRERROR_R_POSIX || defined HAVE_STRERROR_R char errbuf[1024]; -# if STRERROR_R_CHAR_P || _LIBC +# if _LIBC || (!GNULIB_STRERROR_R_POSIX && STRERROR_R_CHAR_P) s = __strerror_r (errnum, errbuf, sizeof errbuf); # else if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0) @@ -132,13 +202,12 @@ print_errno_message (int errnum) #endif } -static void +static void _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0) _GL_ARG_NONNULL ((3)) error_tail (int status, int errnum, const char *message, va_list args) { #if _LIBC if (_IO_fwide (stderr, 0) > 0) { -# define ALLOCA_LIMIT 2000 size_t len = strlen (message) + 1; wchar_t *wmessage = NULL; mbstate_t st; @@ -147,63 +216,62 @@ error_tail (int status, int errnum, const char *message, va_list args) bool use_malloc = false; while (1) - { - if (__libc_use_alloca (len * sizeof (wchar_t))) - wmessage = (wchar_t *) alloca (len * sizeof (wchar_t)); - else - { - if (!use_malloc) - wmessage = NULL; - - wchar_t *p = (wchar_t *) realloc (wmessage, - len * sizeof (wchar_t)); - if (p == NULL) - { - free (wmessage); - fputws_unlocked (L"out of memory\n", stderr); - return; - } - wmessage = p; - use_malloc = true; - } - - memset (&st, '\0', sizeof (st)); - tmp = message; - - res = mbsrtowcs (wmessage, &tmp, len, &st); - if (res != len) - break; - - if (__builtin_expect (len >= SIZE_MAX / 2, 0)) - { - /* This really should not happen if everything is fine. */ - res = (size_t) -1; - break; - } - - len *= 2; - } + { + if (__libc_use_alloca (len * sizeof (wchar_t))) + wmessage = (wchar_t *) alloca (len * sizeof (wchar_t)); + else + { + if (!use_malloc) + wmessage = NULL; + + wchar_t *p = (wchar_t *) realloc (wmessage, + len * sizeof (wchar_t)); + if (p == NULL) + { + free (wmessage); + fputws_unlocked (L"out of memory\n", stderr); + return; + } + wmessage = p; + use_malloc = true; + } + + memset (&st, '\0', sizeof (st)); + tmp = message; + + res = mbsrtowcs (wmessage, &tmp, len, &st); + if (res != len) + break; + + if (__builtin_expect (len >= SIZE_MAX / sizeof (wchar_t) / 2, 0)) + { + /* This really should not happen if everything is fine. */ + res = (size_t) -1; + break; + } + + len *= 2; + } if (res == (size_t) -1) - { - /* The string cannot be converted. */ - if (use_malloc) - { - free (wmessage); - use_malloc = false; - } - wmessage = (wchar_t *) L"???"; - } + { + /* The string cannot be converted. */ + if (use_malloc) + { + free (wmessage); + use_malloc = false; + } + wmessage = (wchar_t *) L"???"; + } __vfwprintf (stderr, wmessage, args); if (use_malloc) - free (wmessage); + free (wmessage); } else #endif vfprintf (stderr, message, args); - va_end (args); ++error_message_count; if (errnum) @@ -233,10 +301,10 @@ error (int status, int errnum, const char *message, ...) cancellation. Therefore disable cancellation for now. */ int state = PTHREAD_CANCEL_ENABLE; __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), - 0); + 0); #endif - fflush (stdout); + flush_stdout (); #ifdef _LIBC _IO_flockfile (stderr); #endif @@ -253,6 +321,7 @@ error (int status, int errnum, const char *message, ...) va_start (args, message); error_tail (status, errnum, message, args); + va_end (args); #ifdef _LIBC _IO_funlockfile (stderr); @@ -268,7 +337,7 @@ int error_one_per_line; void error_at_line (int status, int errnum, const char *file_name, - unsigned int line_number, const char *message, ...) + unsigned int line_number, const char *message, ...) { va_list args; @@ -278,10 +347,13 @@ error_at_line (int status, int errnum, const char *file_name, static unsigned int old_line_number; if (old_line_number == line_number - && (file_name == old_file_name - || strcmp (old_file_name, file_name) == 0)) - /* Simply return and print nothing. */ - return; + && (file_name == old_file_name + || (old_file_name != NULL + && file_name != NULL + && strcmp (old_file_name, file_name) == 0))) + + /* Simply return and print nothing. */ + return; old_file_name = file_name; old_line_number = line_number; @@ -292,10 +364,10 @@ error_at_line (int status, int errnum, const char *file_name, cancellation. Therefore disable cancellation for now. */ int state = PTHREAD_CANCEL_ENABLE; __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), - 0); + 0); #endif - fflush (stdout); + flush_stdout (); #ifdef _LIBC _IO_flockfile (stderr); #endif @@ -311,15 +383,16 @@ error_at_line (int status, int errnum, const char *file_name, } #if _LIBC - __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ", - file_name, line_number); + __fxprintf (NULL, file_name != NULL ? "%s:%u: " : " ", + file_name, line_number); #else - fprintf (stderr, file_name != NULL ? "%s:%d: " : " ", - file_name, line_number); + fprintf (stderr, file_name != NULL ? "%s:%u: " : " ", + file_name, line_number); #endif va_start (args, message); error_tail (status, errnum, message, args); + va_end (args); #ifdef _LIBC _IO_funlockfile (stderr);