@@ -160,6 +160,7 @@ static void send_message_to_server_log(ErrorData *edata);
160160static void send_message_to_frontend (ErrorData * edata );
161161static char * expand_fmt_string (const char * fmt ,ErrorData * edata );
162162static const char * useful_strerror (int errnum );
163+ static const char * get_errno_symbol (int errnum );
163164static const char * error_severity (int elevel );
164165static void append_with_tabs (StringInfo buf ,const char * str );
165166static bool is_log_level_output (int elevel ,int log_min_level );
@@ -2748,7 +2749,7 @@ expand_fmt_string(const char *fmt, ErrorData *edata)
27482749static const char *
27492750useful_strerror (int errnum )
27502751{
2751- /* this buffer is only used iferrno has a bogus value */
2752+ /* this buffer is only used ifstrerror() and get_errno_symbol() fail */
27522753static char errorstr_buf [48 ];
27532754const char * str ;
27542755
@@ -2760,10 +2761,16 @@ useful_strerror(int errnum)
27602761str = strerror (errnum );
27612762
27622763/*
2763- * Some strerror()s return an empty string for out-of-range errno. This is
2764- * ANSI C spec compliant, but not exactly useful.
2764+ * Some strerror()s return an empty string for out-of-range errno.This
2765+ * is ANSI C spec compliant, but not exactly useful. Also, we may get
2766+ * back strings of question marks if libc cannot transcode the message to
2767+ * the codeset specified by LC_CTYPE. If we get nothing useful, first try
2768+ * get_errno_symbol(), and if that fails, print the numeric errno.
27652769 */
2766- if (str == NULL || * str == '\0' )
2770+ if (str == NULL || * str == '\0' || * str == '?' )
2771+ str = get_errno_symbol (errnum );
2772+
2773+ if (str == NULL )
27672774{
27682775snprintf (errorstr_buf ,sizeof (errorstr_buf ),
27692776/*------
@@ -2776,6 +2783,178 @@ useful_strerror(int errnum)
27762783return str ;
27772784}
27782785
2786+ /*
2787+ * Returns a symbol (e.g. "ENOENT") for an errno code.
2788+ * Returns NULL if the code is unrecognized.
2789+ */
2790+ static const char *
2791+ get_errno_symbol (int errnum )
2792+ {
2793+ switch (errnum )
2794+ {
2795+ case E2BIG :
2796+ return "E2BIG" ;
2797+ case EACCES :
2798+ return "EACCES" ;
2799+ #ifdef EADDRINUSE
2800+ case EADDRINUSE :
2801+ return "EADDRINUSE" ;
2802+ #endif
2803+ #ifdef EADDRNOTAVAIL
2804+ case EADDRNOTAVAIL :
2805+ return "EADDRNOTAVAIL" ;
2806+ #endif
2807+ case EAFNOSUPPORT :
2808+ return "EAFNOSUPPORT" ;
2809+ #ifdef EAGAIN
2810+ case EAGAIN :
2811+ return "EAGAIN" ;
2812+ #endif
2813+ #ifdef EALREADY
2814+ case EALREADY :
2815+ return "EALREADY" ;
2816+ #endif
2817+ case EBADF :
2818+ return "EBADF" ;
2819+ #ifdef EBADMSG
2820+ case EBADMSG :
2821+ return "EBADMSG" ;
2822+ #endif
2823+ case EBUSY :
2824+ return "EBUSY" ;
2825+ case ECHILD :
2826+ return "ECHILD" ;
2827+ #ifdef ECONNABORTED
2828+ case ECONNABORTED :
2829+ return "ECONNABORTED" ;
2830+ #endif
2831+ case ECONNREFUSED :
2832+ return "ECONNREFUSED" ;
2833+ #ifdef ECONNRESET
2834+ case ECONNRESET :
2835+ return "ECONNRESET" ;
2836+ #endif
2837+ case EDEADLK :
2838+ return "EDEADLK" ;
2839+ case EDOM :
2840+ return "EDOM" ;
2841+ case EEXIST :
2842+ return "EEXIST" ;
2843+ case EFAULT :
2844+ return "EFAULT" ;
2845+ case EFBIG :
2846+ return "EFBIG" ;
2847+ #ifdef EHOSTUNREACH
2848+ case EHOSTUNREACH :
2849+ return "EHOSTUNREACH" ;
2850+ #endif
2851+ case EIDRM :
2852+ return "EIDRM" ;
2853+ case EINPROGRESS :
2854+ return "EINPROGRESS" ;
2855+ case EINTR :
2856+ return "EINTR" ;
2857+ case EINVAL :
2858+ return "EINVAL" ;
2859+ case EIO :
2860+ return "EIO" ;
2861+ #ifdef EISCONN
2862+ case EISCONN :
2863+ return "EISCONN" ;
2864+ #endif
2865+ case EISDIR :
2866+ return "EISDIR" ;
2867+ #ifdef ELOOP
2868+ case ELOOP :
2869+ return "ELOOP" ;
2870+ #endif
2871+ case EMFILE :
2872+ return "EMFILE" ;
2873+ case EMLINK :
2874+ return "EMLINK" ;
2875+ case EMSGSIZE :
2876+ return "EMSGSIZE" ;
2877+ case ENAMETOOLONG :
2878+ return "ENAMETOOLONG" ;
2879+ case ENFILE :
2880+ return "ENFILE" ;
2881+ case ENOBUFS :
2882+ return "ENOBUFS" ;
2883+ case ENODEV :
2884+ return "ENODEV" ;
2885+ case ENOENT :
2886+ return "ENOENT" ;
2887+ case ENOEXEC :
2888+ return "ENOEXEC" ;
2889+ case ENOMEM :
2890+ return "ENOMEM" ;
2891+ case ENOSPC :
2892+ return "ENOSPC" ;
2893+ case ENOSYS :
2894+ return "ENOSYS" ;
2895+ #ifdef ENOTCONN
2896+ case ENOTCONN :
2897+ return "ENOTCONN" ;
2898+ #endif
2899+ case ENOTDIR :
2900+ return "ENOTDIR" ;
2901+ #if defined(ENOTEMPTY )&& (ENOTEMPTY != EEXIST )/* same code on AIX */
2902+ case ENOTEMPTY :
2903+ return "ENOTEMPTY" ;
2904+ #endif
2905+ #ifdef ENOTSOCK
2906+ case ENOTSOCK :
2907+ return "ENOTSOCK" ;
2908+ #endif
2909+ #ifdef ENOTSUP
2910+ case ENOTSUP :
2911+ return "ENOTSUP" ;
2912+ #endif
2913+ case ENOTTY :
2914+ return "ENOTTY" ;
2915+ case ENXIO :
2916+ return "ENXIO" ;
2917+ #if defined(EOPNOTSUPP )&& (!defined(ENOTSUP )|| (EOPNOTSUPP != ENOTSUP ))
2918+ case EOPNOTSUPP :
2919+ return "EOPNOTSUPP" ;
2920+ #endif
2921+ #ifdef EOVERFLOW
2922+ case EOVERFLOW :
2923+ return "EOVERFLOW" ;
2924+ #endif
2925+ case EPERM :
2926+ return "EPERM" ;
2927+ case EPIPE :
2928+ return "EPIPE" ;
2929+ case EPROTONOSUPPORT :
2930+ return "EPROTONOSUPPORT" ;
2931+ case ERANGE :
2932+ return "ERANGE" ;
2933+ #ifdef EROFS
2934+ case EROFS :
2935+ return "EROFS" ;
2936+ #endif
2937+ case ESRCH :
2938+ return "ESRCH" ;
2939+ #ifdef ETIMEDOUT
2940+ case ETIMEDOUT :
2941+ return "ETIMEDOUT" ;
2942+ #endif
2943+ #ifdef ETXTBSY
2944+ case ETXTBSY :
2945+ return "ETXTBSY" ;
2946+ #endif
2947+ #if defined(EWOULDBLOCK )&& (!defined(EAGAIN )|| (EWOULDBLOCK != EAGAIN ))
2948+ case EWOULDBLOCK :
2949+ return "EWOULDBLOCK" ;
2950+ #endif
2951+ case EXDEV :
2952+ return "EXDEV" ;
2953+ }
2954+
2955+ return NULL ;
2956+ }
2957+
27792958
27802959/*
27812960 * error_severity --- get localized string representing elevel