@@ -170,6 +170,7 @@ static void send_message_to_server_log(ErrorData *edata);
170170static void send_message_to_frontend (ErrorData * edata );
171171static char * expand_fmt_string (const char * fmt ,ErrorData * edata );
172172static const char * useful_strerror (int errnum );
173+ static const char * get_errno_symbol (int errnum );
173174static const char * error_severity (int elevel );
174175static void append_with_tabs (StringInfo buf ,const char * str );
175176static bool is_log_level_output (int elevel ,int log_min_level );
@@ -2784,7 +2785,7 @@ expand_fmt_string(const char *fmt, ErrorData *edata)
27842785static const char *
27852786useful_strerror (int errnum )
27862787{
2787- /* this buffer is only used iferrno has a bogus value */
2788+ /* this buffer is only used ifstrerror() and get_errno_symbol() fail */
27882789static char errorstr_buf [48 ];
27892790const char * str ;
27902791
@@ -2796,10 +2797,16 @@ useful_strerror(int errnum)
27962797str = strerror (errnum );
27972798
27982799/*
2799- * Some strerror()s return an empty string for out-of-range errno. This is
2800- * ANSI C spec compliant, but not exactly useful.
2800+ * Some strerror()s return an empty string for out-of-range errno.This
2801+ * is ANSI C spec compliant, but not exactly useful. Also, we may get
2802+ * back strings of question marks if libc cannot transcode the message to
2803+ * the codeset specified by LC_CTYPE. If we get nothing useful, first try
2804+ * get_errno_symbol(), and if that fails, print the numeric errno.
28012805 */
2802- if (str == NULL || * str == '\0' )
2806+ if (str == NULL || * str == '\0' || * str == '?' )
2807+ str = get_errno_symbol (errnum );
2808+
2809+ if (str == NULL )
28032810{
28042811snprintf (errorstr_buf ,sizeof (errorstr_buf ),
28052812/*------
@@ -2812,6 +2819,178 @@ useful_strerror(int errnum)
28122819return str ;
28132820}
28142821
2822+ /*
2823+ * Returns a symbol (e.g. "ENOENT") for an errno code.
2824+ * Returns NULL if the code is unrecognized.
2825+ */
2826+ static const char *
2827+ get_errno_symbol (int errnum )
2828+ {
2829+ switch (errnum )
2830+ {
2831+ case E2BIG :
2832+ return "E2BIG" ;
2833+ case EACCES :
2834+ return "EACCES" ;
2835+ #ifdef EADDRINUSE
2836+ case EADDRINUSE :
2837+ return "EADDRINUSE" ;
2838+ #endif
2839+ #ifdef EADDRNOTAVAIL
2840+ case EADDRNOTAVAIL :
2841+ return "EADDRNOTAVAIL" ;
2842+ #endif
2843+ case EAFNOSUPPORT :
2844+ return "EAFNOSUPPORT" ;
2845+ #ifdef EAGAIN
2846+ case EAGAIN :
2847+ return "EAGAIN" ;
2848+ #endif
2849+ #ifdef EALREADY
2850+ case EALREADY :
2851+ return "EALREADY" ;
2852+ #endif
2853+ case EBADF :
2854+ return "EBADF" ;
2855+ #ifdef EBADMSG
2856+ case EBADMSG :
2857+ return "EBADMSG" ;
2858+ #endif
2859+ case EBUSY :
2860+ return "EBUSY" ;
2861+ case ECHILD :
2862+ return "ECHILD" ;
2863+ #ifdef ECONNABORTED
2864+ case ECONNABORTED :
2865+ return "ECONNABORTED" ;
2866+ #endif
2867+ case ECONNREFUSED :
2868+ return "ECONNREFUSED" ;
2869+ #ifdef ECONNRESET
2870+ case ECONNRESET :
2871+ return "ECONNRESET" ;
2872+ #endif
2873+ case EDEADLK :
2874+ return "EDEADLK" ;
2875+ case EDOM :
2876+ return "EDOM" ;
2877+ case EEXIST :
2878+ return "EEXIST" ;
2879+ case EFAULT :
2880+ return "EFAULT" ;
2881+ case EFBIG :
2882+ return "EFBIG" ;
2883+ #ifdef EHOSTUNREACH
2884+ case EHOSTUNREACH :
2885+ return "EHOSTUNREACH" ;
2886+ #endif
2887+ case EIDRM :
2888+ return "EIDRM" ;
2889+ case EINPROGRESS :
2890+ return "EINPROGRESS" ;
2891+ case EINTR :
2892+ return "EINTR" ;
2893+ case EINVAL :
2894+ return "EINVAL" ;
2895+ case EIO :
2896+ return "EIO" ;
2897+ #ifdef EISCONN
2898+ case EISCONN :
2899+ return "EISCONN" ;
2900+ #endif
2901+ case EISDIR :
2902+ return "EISDIR" ;
2903+ #ifdef ELOOP
2904+ case ELOOP :
2905+ return "ELOOP" ;
2906+ #endif
2907+ case EMFILE :
2908+ return "EMFILE" ;
2909+ case EMLINK :
2910+ return "EMLINK" ;
2911+ case EMSGSIZE :
2912+ return "EMSGSIZE" ;
2913+ case ENAMETOOLONG :
2914+ return "ENAMETOOLONG" ;
2915+ case ENFILE :
2916+ return "ENFILE" ;
2917+ case ENOBUFS :
2918+ return "ENOBUFS" ;
2919+ case ENODEV :
2920+ return "ENODEV" ;
2921+ case ENOENT :
2922+ return "ENOENT" ;
2923+ case ENOEXEC :
2924+ return "ENOEXEC" ;
2925+ case ENOMEM :
2926+ return "ENOMEM" ;
2927+ case ENOSPC :
2928+ return "ENOSPC" ;
2929+ case ENOSYS :
2930+ return "ENOSYS" ;
2931+ #ifdef ENOTCONN
2932+ case ENOTCONN :
2933+ return "ENOTCONN" ;
2934+ #endif
2935+ case ENOTDIR :
2936+ return "ENOTDIR" ;
2937+ #if defined(ENOTEMPTY )&& (ENOTEMPTY != EEXIST )/* same code on AIX */
2938+ case ENOTEMPTY :
2939+ return "ENOTEMPTY" ;
2940+ #endif
2941+ #ifdef ENOTSOCK
2942+ case ENOTSOCK :
2943+ return "ENOTSOCK" ;
2944+ #endif
2945+ #ifdef ENOTSUP
2946+ case ENOTSUP :
2947+ return "ENOTSUP" ;
2948+ #endif
2949+ case ENOTTY :
2950+ return "ENOTTY" ;
2951+ case ENXIO :
2952+ return "ENXIO" ;
2953+ #if defined(EOPNOTSUPP )&& (!defined(ENOTSUP )|| (EOPNOTSUPP != ENOTSUP ))
2954+ case EOPNOTSUPP :
2955+ return "EOPNOTSUPP" ;
2956+ #endif
2957+ #ifdef EOVERFLOW
2958+ case EOVERFLOW :
2959+ return "EOVERFLOW" ;
2960+ #endif
2961+ case EPERM :
2962+ return "EPERM" ;
2963+ case EPIPE :
2964+ return "EPIPE" ;
2965+ case EPROTONOSUPPORT :
2966+ return "EPROTONOSUPPORT" ;
2967+ case ERANGE :
2968+ return "ERANGE" ;
2969+ #ifdef EROFS
2970+ case EROFS :
2971+ return "EROFS" ;
2972+ #endif
2973+ case ESRCH :
2974+ return "ESRCH" ;
2975+ #ifdef ETIMEDOUT
2976+ case ETIMEDOUT :
2977+ return "ETIMEDOUT" ;
2978+ #endif
2979+ #ifdef ETXTBSY
2980+ case ETXTBSY :
2981+ return "ETXTBSY" ;
2982+ #endif
2983+ #if defined(EWOULDBLOCK )&& (!defined(EAGAIN )|| (EWOULDBLOCK != EAGAIN ))
2984+ case EWOULDBLOCK :
2985+ return "EWOULDBLOCK" ;
2986+ #endif
2987+ case EXDEV :
2988+ return "EXDEV" ;
2989+ }
2990+
2991+ return NULL ;
2992+ }
2993+
28152994
28162995/*
28172996 * error_severity --- get localized string representing elevel