diff options
-rwxr-xr-x | configure | 13 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | src/backend/port/win32/socket.c | 36 | ||||
-rw-r--r-- | src/backend/utils/error/elog.c | 217 | ||||
-rw-r--r-- | src/include/pg_config.h.in | 3 | ||||
-rw-r--r-- | src/include/pg_config.h.win32 | 5 | ||||
-rw-r--r-- | src/include/port.h | 8 | ||||
-rw-r--r-- | src/include/port/win32_port.h | 6 | ||||
-rw-r--r-- | src/interfaces/ecpg/compatlib/.gitignore | 1 | ||||
-rw-r--r-- | src/interfaces/ecpg/compatlib/Makefile | 6 | ||||
-rw-r--r-- | src/interfaces/ecpg/ecpglib/.gitignore | 1 | ||||
-rw-r--r-- | src/interfaces/ecpg/ecpglib/Makefile | 6 | ||||
-rw-r--r-- | src/interfaces/ecpg/pgtypeslib/.gitignore | 1 | ||||
-rw-r--r-- | src/interfaces/ecpg/pgtypeslib/Makefile | 6 | ||||
-rw-r--r-- | src/interfaces/libpq/Makefile | 4 | ||||
-rw-r--r-- | src/pl/plpython/plpython.h | 1 | ||||
-rw-r--r-- | src/port/Makefile | 2 | ||||
-rw-r--r-- | src/port/strerror.c | 289 | ||||
-rw-r--r-- | src/tools/msvc/Mkvcbuild.pm | 3 |
19 files changed, 299 insertions, 311 deletions
diff --git a/configure b/configure index 23ebfa8f3d0..508e3ce9c53 100755 --- a/configure +++ b/configure @@ -15644,19 +15644,6 @@ esac fi -ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror" -if test "x$ac_cv_func_strerror" = xyes; then : - $as_echo "#define HAVE_STRERROR 1" >>confdefs.h - -else - case " $LIBOBJS " in - *" strerror.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS strerror.$ac_objext" - ;; -esac - -fi - ac_fn_c_check_func "$LINENO" "strlcat" "ac_cv_func_strlcat" if test "x$ac_cv_func_strlcat" = xyes; then : $as_echo "#define HAVE_STRLCAT 1" >>confdefs.h diff --git a/configure.in b/configure.in index 530f2759936..70de4a1aa7a 100644 --- a/configure.in +++ b/configure.in @@ -1687,7 +1687,7 @@ else AC_CHECK_FUNCS([fpclass fp_class fp_class_d class], [break]) fi -AC_REPLACE_FUNCS([crypt dlopen fls getopt getrusage inet_aton mkdtemp random rint srandom strerror strlcat strlcpy strnlen]) +AC_REPLACE_FUNCS([crypt dlopen fls getopt getrusage inet_aton mkdtemp random rint srandom strlcat strlcpy strnlen]) case $host_os in diff --git a/src/backend/port/win32/socket.c b/src/backend/port/win32/socket.c index f4356fe1f31..af35cfbbb35 100644 --- a/src/backend/port/win32/socket.c +++ b/src/backend/port/win32/socket.c @@ -690,39 +690,3 @@ pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, c memcpy(writefds, &outwritefds, sizeof(fd_set)); return nummatches; } - - -/* - * Return win32 error string, since strerror can't - * handle winsock codes - */ -static char wserrbuf[256]; -const char * -pgwin32_socket_strerror(int err) -{ - static HANDLE handleDLL = INVALID_HANDLE_VALUE; - - if (handleDLL == INVALID_HANDLE_VALUE) - { - handleDLL = LoadLibraryEx("netmsg.dll", NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); - if (handleDLL == NULL) - ereport(FATAL, - (errmsg_internal("could not load netmsg.dll: error code %lu", GetLastError()))); - } - - ZeroMemory(&wserrbuf, sizeof(wserrbuf)); - if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_FROM_HMODULE, - handleDLL, - err, - MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), - wserrbuf, - sizeof(wserrbuf) - 1, - NULL) == 0) - { - /* Failed to get id */ - sprintf(wserrbuf, "unrecognized winsock error %d", err); - } - return wserrbuf; -} diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 16531f7a0f1..22e5d876181 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -178,8 +178,6 @@ static void send_message_to_server_log(ErrorData *edata); static void write_pipe_chunks(char *data, int len, int dest); static void send_message_to_frontend(ErrorData *edata); static char *expand_fmt_string(const char *fmt, ErrorData *edata); -static const char *useful_strerror(int errnum); -static const char *get_errno_symbol(int errnum); static const char *error_severity(int elevel); static void append_with_tabs(StringInfo buf, const char *str); static bool is_log_level_output(int elevel, int log_min_level); @@ -3360,7 +3358,7 @@ expand_fmt_string(const char *fmt, ErrorData *edata) */ const char *cp2; - cp2 = useful_strerror(edata->saved_errno); + cp2 = strerror(edata->saved_errno); for (; *cp2; cp2++) { if (*cp2 == '%') @@ -3384,219 +3382,6 @@ expand_fmt_string(const char *fmt, ErrorData *edata) /* - * A slightly cleaned-up version of strerror() - */ -static const char * -useful_strerror(int errnum) -{ - /* this buffer is only used if strerror() and get_errno_symbol() fail */ - static char errorstr_buf[48]; - const char *str; - -#ifdef WIN32 - /* Winsock error code range, per WinError.h */ - if (errnum >= 10000 && errnum <= 11999) - return pgwin32_socket_strerror(errnum); -#endif - str = strerror(errnum); - - /* - * Some strerror()s return an empty string for out-of-range errno. This - * is ANSI C spec compliant, but not exactly useful. Also, we may get - * back strings of question marks if libc cannot transcode the message to - * the codeset specified by LC_CTYPE. If we get nothing useful, first try - * get_errno_symbol(), and if that fails, print the numeric errno. - */ - if (str == NULL || *str == '\0' || *str == '?') - str = get_errno_symbol(errnum); - - if (str == NULL) - { - snprintf(errorstr_buf, sizeof(errorstr_buf), - /*------ - translator: This string will be truncated at 47 - characters expanded. */ - _("operating system error %d"), errnum); - str = errorstr_buf; - } - - return str; -} - -/* - * Returns a symbol (e.g. "ENOENT") for an errno code. - * Returns NULL if the code is unrecognized. - */ -static const char * -get_errno_symbol(int errnum) -{ - switch (errnum) - { - case E2BIG: - return "E2BIG"; - case EACCES: - return "EACCES"; -#ifdef EADDRINUSE - case EADDRINUSE: - return "EADDRINUSE"; -#endif -#ifdef EADDRNOTAVAIL - case EADDRNOTAVAIL: - return "EADDRNOTAVAIL"; -#endif - case EAFNOSUPPORT: - return "EAFNOSUPPORT"; -#ifdef EAGAIN - case EAGAIN: - return "EAGAIN"; -#endif -#ifdef EALREADY - case EALREADY: - return "EALREADY"; -#endif - case EBADF: - return "EBADF"; -#ifdef EBADMSG - case EBADMSG: - return "EBADMSG"; -#endif - case EBUSY: - return "EBUSY"; - case ECHILD: - return "ECHILD"; -#ifdef ECONNABORTED - case ECONNABORTED: - return "ECONNABORTED"; -#endif - case ECONNREFUSED: - return "ECONNREFUSED"; -#ifdef ECONNRESET - case ECONNRESET: - return "ECONNRESET"; -#endif - case EDEADLK: - return "EDEADLK"; - case EDOM: - return "EDOM"; - case EEXIST: - return "EEXIST"; - case EFAULT: - return "EFAULT"; - case EFBIG: - return "EFBIG"; -#ifdef EHOSTUNREACH - case EHOSTUNREACH: - return "EHOSTUNREACH"; -#endif - case EIDRM: - return "EIDRM"; - case EINPROGRESS: - return "EINPROGRESS"; - case EINTR: - return "EINTR"; - case EINVAL: - return "EINVAL"; - case EIO: - return "EIO"; -#ifdef EISCONN - case EISCONN: - return "EISCONN"; -#endif - case EISDIR: - return "EISDIR"; -#ifdef ELOOP - case ELOOP: - return "ELOOP"; -#endif - case EMFILE: - return "EMFILE"; - case EMLINK: - return "EMLINK"; - case EMSGSIZE: - return "EMSGSIZE"; - case ENAMETOOLONG: - return "ENAMETOOLONG"; - case ENFILE: - return "ENFILE"; - case ENOBUFS: - return "ENOBUFS"; - case ENODEV: - return "ENODEV"; - case ENOENT: - return "ENOENT"; - case ENOEXEC: - return "ENOEXEC"; - case ENOMEM: - return "ENOMEM"; - case ENOSPC: - return "ENOSPC"; - case ENOSYS: - return "ENOSYS"; -#ifdef ENOTCONN - case ENOTCONN: - return "ENOTCONN"; -#endif - case ENOTDIR: - return "ENOTDIR"; -#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */ - case ENOTEMPTY: - return "ENOTEMPTY"; -#endif -#ifdef ENOTSOCK - case ENOTSOCK: - return "ENOTSOCK"; -#endif -#ifdef ENOTSUP - case ENOTSUP: - return "ENOTSUP"; -#endif - case ENOTTY: - return "ENOTTY"; - case ENXIO: - return "ENXIO"; -#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (EOPNOTSUPP != ENOTSUP)) - case EOPNOTSUPP: - return "EOPNOTSUPP"; -#endif -#ifdef EOVERFLOW - case EOVERFLOW: - return "EOVERFLOW"; -#endif - case EPERM: - return "EPERM"; - case EPIPE: - return "EPIPE"; - case EPROTONOSUPPORT: - return "EPROTONOSUPPORT"; - case ERANGE: - return "ERANGE"; -#ifdef EROFS - case EROFS: - return "EROFS"; -#endif - case ESRCH: - return "ESRCH"; -#ifdef ETIMEDOUT - case ETIMEDOUT: - return "ETIMEDOUT"; -#endif -#ifdef ETXTBSY - case ETXTBSY: - return "ETXTBSY"; -#endif -#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) - case EWOULDBLOCK: - return "EWOULDBLOCK"; -#endif - case EXDEV: - return "EXDEV"; - } - - return NULL; -} - - -/* * error_severity --- get string representing elevel * * The string is not localized here, but we mark the strings for translation diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 5d4079609cc..e576831a715 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -534,9 +534,6 @@ /* Define to 1 if you have the <stdlib.h> header file. */ #undef HAVE_STDLIB_H -/* Define to 1 if you have the `strerror' function. */ -#undef HAVE_STRERROR - /* Define to 1 if you have the `strerror_r' function. */ #undef HAVE_STRERROR_R diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32 index 182698a0872..536f06c38cb 100644 --- a/src/include/pg_config.h.win32 +++ b/src/include/pg_config.h.win32 @@ -405,11 +405,6 @@ /* Define to 1 if you have the <stdlib.h> header file. */ #define HAVE_STDLIB_H 1 -/* Define to 1 if you have the `strerror' function. */ -#ifndef HAVE_STRERROR -#define HAVE_STRERROR 1 -#endif - /* Define to 1 if you have the `strerror_r' function. */ /* #undef HAVE_STRERROR_R */ diff --git a/src/include/port.h b/src/include/port.h index 2522ebc35f8..acf8d5fefd7 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -189,6 +189,10 @@ extern int pg_printf(const char *fmt,...) pg_attribute_printf(1, 2); #endif #endif /* USE_REPL_SNPRINTF */ +/* Replace strerror() with our own, somewhat more robust wrapper */ +extern char *pg_strerror(int errnum); +#define strerror pg_strerror + /* Portable prompt handling */ extern void simple_prompt(const char *prompt, char *destination, size_t destlen, bool echo); @@ -355,7 +359,7 @@ extern int isinf(double x); #undef isinf #define isinf __builtin_isinf #endif /* __has_builtin(isinf) */ -#endif /* __clang__ && !__cplusplus*/ +#endif /* __clang__ && !__cplusplus */ #endif /* !HAVE_ISINF */ #ifndef HAVE_MKDTEMP @@ -403,7 +407,7 @@ extern void srandom(unsigned int seed); #ifndef HAVE_DLOPEN extern void *dlopen(const char *file, int mode); extern void *dlsym(void *handle, const char *symbol); -extern int dlclose(void *handle); +extern int dlclose(void *handle); extern char *dlerror(void); #endif diff --git a/src/include/port/win32_port.h b/src/include/port/win32_port.h index b398cd3b975..360dbdf3a75 100644 --- a/src/include/port/win32_port.h +++ b/src/include/port/win32_port.h @@ -322,8 +322,8 @@ extern int pgwin32_safestat(const char *path, struct stat *buf); * Supplement to <errno.h>. * * We redefine network-related Berkeley error symbols as the corresponding WSA - * constants. This allows elog.c to recognize them as being in the Winsock - * error code range and pass them off to pgwin32_socket_strerror(), since + * constants. This allows strerror.c to recognize them as being in the Winsock + * error code range and pass them off to win32_socket_strerror(), since * Windows' version of plain strerror() won't cope. Note that this will break * if these names are used for anything else besides Windows Sockets errors. * See TranslateSocketError() when changing this list. @@ -456,8 +456,6 @@ int pgwin32_connect(SOCKET s, const struct sockaddr *name, int namelen); int pgwin32_select(int nfds, fd_set *readfs, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout); int pgwin32_recv(SOCKET s, char *buf, int len, int flags); int pgwin32_send(SOCKET s, const void *buf, int len, int flags); - -const char *pgwin32_socket_strerror(int err); int pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout); extern int pgwin32_noblock; diff --git a/src/interfaces/ecpg/compatlib/.gitignore b/src/interfaces/ecpg/compatlib/.gitignore index ad5ba1354ca..8b9aa950afe 100644 --- a/src/interfaces/ecpg/compatlib/.gitignore +++ b/src/interfaces/ecpg/compatlib/.gitignore @@ -2,4 +2,5 @@ /blibecpg_compatdll.def /exports.list /snprintf.c +/strerror.c /strnlen.c diff --git a/src/interfaces/ecpg/compatlib/Makefile b/src/interfaces/ecpg/compatlib/Makefile index ebfd89544aa..b7bd1629027 100644 --- a/src/interfaces/ecpg/compatlib/Makefile +++ b/src/interfaces/ecpg/compatlib/Makefile @@ -31,7 +31,7 @@ SHLIB_EXPORTS = exports.txt # Need to recompile any libpgport object files LIBS := $(filter-out -lpgport, $(LIBS)) -OBJS= informix.o $(filter snprintf.o strnlen.o, $(LIBOBJS)) $(WIN32RES) +OBJS= informix.o strerror.o $(filter snprintf.o strnlen.o, $(LIBOBJS)) $(WIN32RES) PKG_CONFIG_REQUIRES_PRIVATE = libecpg libpgtypes @@ -48,7 +48,7 @@ submake-pgtypeslib: # Shared library stuff include $(top_srcdir)/src/Makefile.shlib -snprintf.c strnlen.c: % : $(top_srcdir)/src/port/% +snprintf.c strerror.c strnlen.c: % : $(top_srcdir)/src/port/% rm -f $@ && $(LN_S) $< . install: all installdirs install-lib @@ -58,6 +58,6 @@ installdirs: installdirs-lib uninstall: uninstall-lib clean distclean: clean-lib - rm -f $(OBJS) snprintf.c strnlen.c + rm -f $(OBJS) snprintf.c strerror.c strnlen.c maintainer-clean: distclean maintainer-clean-lib diff --git a/src/interfaces/ecpg/ecpglib/.gitignore b/src/interfaces/ecpg/ecpglib/.gitignore index 1619e970c29..545c106a9ed 100644 --- a/src/interfaces/ecpg/ecpglib/.gitignore +++ b/src/interfaces/ecpg/ecpglib/.gitignore @@ -4,6 +4,7 @@ /path.c /pgstrcasecmp.c /snprintf.c +/strerror.c /strlcpy.c /strnlen.c /thread.c diff --git a/src/interfaces/ecpg/ecpglib/Makefile b/src/interfaces/ecpg/ecpglib/Makefile index d25d248616d..005d25a2bcd 100644 --- a/src/interfaces/ecpg/ecpglib/Makefile +++ b/src/interfaces/ecpg/ecpglib/Makefile @@ -26,7 +26,7 @@ override CFLAGS += $(PTHREAD_CFLAGS) LIBS := $(filter-out -lpgport, $(LIBS)) OBJS= execute.o typename.o descriptor.o sqlda.o data.o error.o prepare.o memory.o \ - connect.o misc.o path.o pgstrcasecmp.o \ + connect.o misc.o path.o pgstrcasecmp.o strerror.o \ $(filter snprintf.o strlcpy.o strnlen.o win32setlocale.o isinf.o, $(LIBOBJS)) \ $(WIN32RES) @@ -57,7 +57,7 @@ include $(top_srcdir)/src/Makefile.shlib # necessarily use the same object files as the backend uses. Instead, # symlink the source files in here and build our own object file. -path.c pgstrcasecmp.c snprintf.c strlcpy.c strnlen.c thread.c win32setlocale.c isinf.c: % : $(top_srcdir)/src/port/% +path.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c strnlen.c thread.c win32setlocale.c isinf.c: % : $(top_srcdir)/src/port/% rm -f $@ && $(LN_S) $< . misc.o: misc.c $(top_builddir)/src/port/pg_config_paths.h @@ -74,6 +74,6 @@ uninstall: uninstall-lib clean distclean: clean-lib rm -f $(OBJS) - rm -f path.c pgstrcasecmp.c snprintf.c strlcpy.c strnlen.c thread.c win32setlocale.c isinf.c + rm -f path.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c strnlen.c thread.c win32setlocale.c isinf.c maintainer-clean: distclean maintainer-clean-lib diff --git a/src/interfaces/ecpg/pgtypeslib/.gitignore b/src/interfaces/ecpg/pgtypeslib/.gitignore index d5f0fae445a..b3fae08d2f4 100644 --- a/src/interfaces/ecpg/pgtypeslib/.gitignore +++ b/src/interfaces/ecpg/pgtypeslib/.gitignore @@ -4,5 +4,6 @@ /pgstrcasecmp.c /rint.c /snprintf.c +/strerror.c /string.c /strnlen.c diff --git a/src/interfaces/ecpg/pgtypeslib/Makefile b/src/interfaces/ecpg/pgtypeslib/Makefile index 29264ce7b7b..18b2402d0f3 100644 --- a/src/interfaces/ecpg/pgtypeslib/Makefile +++ b/src/interfaces/ecpg/pgtypeslib/Makefile @@ -30,7 +30,7 @@ SHLIB_LINK += $(filter -lm, $(LIBS)) SHLIB_EXPORTS = exports.txt OBJS= numeric.o datetime.o common.o dt_common.o timestamp.o interval.o \ - pgstrcasecmp.o \ + pgstrcasecmp.o strerror.o \ $(filter rint.o snprintf.o strnlen.o, $(LIBOBJS)) \ string.o \ $(WIN32RES) @@ -45,7 +45,7 @@ include $(top_srcdir)/src/Makefile.shlib # necessarily use the same object files as the backend uses. Instead, # symlink the source files in here and build our own object file. -pgstrcasecmp.c rint.c snprintf.c strnlen.c: % : $(top_srcdir)/src/port/% +pgstrcasecmp.c rint.c snprintf.c strerror.c strnlen.c: % : $(top_srcdir)/src/port/% rm -f $@ && $(LN_S) $< . string.c: % : $(top_srcdir)/src/common/% @@ -58,6 +58,6 @@ installdirs: installdirs-lib uninstall: uninstall-lib clean distclean: clean-lib - rm -f $(OBJS) pgstrcasecmp.c rint.c snprintf.c strnlen.c string.c + rm -f $(OBJS) pgstrcasecmp.c rint.c snprintf.c strerror.c strnlen.c string.c maintainer-clean: distclean maintainer-clean-lib diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile index ec0122a9012..8324f4f057d 100644 --- a/src/interfaces/libpq/Makefile +++ b/src/interfaces/libpq/Makefile @@ -36,9 +36,9 @@ OBJS= fe-auth.o fe-auth-scram.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-l libpq-events.o # libpgport C files we always use OBJS += chklocale.o inet_net_ntop.o noblock.o pgstrcasecmp.o pqsignal.o \ - thread.o + strerror.o thread.o # libpgport C files that are needed if identified by configure -OBJS += $(filter crypt.o getaddrinfo.o getpeereid.o inet_aton.o open.o system.o snprintf.o strerror.o strlcpy.o strnlen.o win32error.o win32setlocale.o, $(LIBOBJS)) +OBJS += $(filter crypt.o getaddrinfo.o getpeereid.o inet_aton.o open.o system.o snprintf.o strlcpy.o strnlen.o win32error.o win32setlocale.o, $(LIBOBJS)) ifeq ($(enable_strong_random), yes) OBJS += pg_strong_random.o diff --git a/src/pl/plpython/plpython.h b/src/pl/plpython/plpython.h index 5c2e6a83f30..6cc323a568d 100644 --- a/src/pl/plpython/plpython.h +++ b/src/pl/plpython/plpython.h @@ -27,7 +27,6 @@ */ #undef _POSIX_C_SOURCE #undef _XOPEN_SOURCE -#undef HAVE_STRERROR #undef HAVE_TZNAME /* diff --git a/src/port/Makefile b/src/port/Makefile index d7467fb0788..b3a10ba014f 100644 --- a/src/port/Makefile +++ b/src/port/Makefile @@ -33,7 +33,7 @@ LIBS += $(PTHREAD_LIBS) OBJS = $(LIBOBJS) $(PG_CRC32C_OBJS) chklocale.o erand48.o inet_net_ntop.o \ noblock.o path.o pgcheckdir.o pgmkdirp.o pgsleep.o \ pgstrcasecmp.o pqsignal.o \ - qsort.o qsort_arg.o quotes.o sprompt.o tar.o thread.o + qsort.o qsort_arg.o quotes.o sprompt.o strerror.o tar.o thread.o ifeq ($(enable_strong_random), yes) OBJS += pg_strong_random.o diff --git a/src/port/strerror.c b/src/port/strerror.c index e92ebc9f55a..ca6910d2e6c 100644 --- a/src/port/strerror.c +++ b/src/port/strerror.c @@ -1,30 +1,285 @@ -/* src/port/strerror.c */ - -/* - * strerror - map error number to descriptive string +/*------------------------------------------------------------------------- + * + * strerror.c + * Replacement for standard strerror() function + * + * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * * - * This version is obviously somewhat Unix-specific. + * IDENTIFICATION + * src/port/strerror.c * - * based on code by Henry Spencer - * modified for ANSI by D'Arcy J.M. Cain + *------------------------------------------------------------------------- */ - #include "c.h" +/* + * Within this file, "strerror" means the platform's function not pg_strerror + */ +#undef strerror -extern const char *const sys_errlist[]; -extern int sys_nerr; +static char *get_errno_symbol(int errnum); +#ifdef WIN32 +static char *win32_socket_strerror(int errnum); +#endif -const char * -strerror(int errnum) + +/* + * A slightly cleaned-up version of strerror() + */ +char * +pg_strerror(int errnum) { - static char buf[24]; + /* this buffer is only used if strerror() and get_errno_symbol() fail */ + static char errorstr_buf[48]; + char *str; + + /* If it's a Windows Winsock error, that needs special handling */ +#ifdef WIN32 + /* Winsock error code range, per WinError.h */ + if (errnum >= 10000 && errnum <= 11999) + return win32_socket_strerror(errnum); +#endif + + /* Try the platform's strerror() */ + str = strerror(errnum); - if (errnum < 0 || errnum > sys_nerr) + /* + * Some strerror()s return an empty string for out-of-range errno. This + * is ANSI C spec compliant, but not exactly useful. Also, we may get + * back strings of question marks if libc cannot transcode the message to + * the codeset specified by LC_CTYPE. If we get nothing useful, first try + * get_errno_symbol(), and if that fails, print the numeric errno. + */ + if (str == NULL || *str == '\0' || *str == '?') + str = get_errno_symbol(errnum); + + if (str == NULL) { - sprintf(buf, _("unrecognized error %d"), errnum); - return buf; + snprintf(errorstr_buf, sizeof(errorstr_buf), + /*------ + translator: This string will be truncated at 47 + characters expanded. */ + _("operating system error %d"), errnum); + str = errorstr_buf; } - return sys_errlist[errnum]; + return str; } + +/* + * Returns a symbol (e.g. "ENOENT") for an errno code. + * Returns NULL if the code is unrecognized. + */ +static char * +get_errno_symbol(int errnum) +{ + switch (errnum) + { + case E2BIG: + return "E2BIG"; + case EACCES: + return "EACCES"; +#ifdef EADDRINUSE + case EADDRINUSE: + return "EADDRINUSE"; +#endif +#ifdef EADDRNOTAVAIL + case EADDRNOTAVAIL: + return "EADDRNOTAVAIL"; +#endif + case EAFNOSUPPORT: + return "EAFNOSUPPORT"; +#ifdef EAGAIN + case EAGAIN: + return "EAGAIN"; +#endif +#ifdef EALREADY + case EALREADY: + return "EALREADY"; +#endif + case EBADF: + return "EBADF"; +#ifdef EBADMSG + case EBADMSG: + return "EBADMSG"; +#endif + case EBUSY: + return "EBUSY"; + case ECHILD: + return "ECHILD"; +#ifdef ECONNABORTED + case ECONNABORTED: + return "ECONNABORTED"; +#endif + case ECONNREFUSED: + return "ECONNREFUSED"; +#ifdef ECONNRESET + case ECONNRESET: + return "ECONNRESET"; +#endif + case EDEADLK: + return "EDEADLK"; + case EDOM: + return "EDOM"; + case EEXIST: + return "EEXIST"; + case EFAULT: + return "EFAULT"; + case EFBIG: + return "EFBIG"; +#ifdef EHOSTUNREACH + case EHOSTUNREACH: + return "EHOSTUNREACH"; +#endif + case EIDRM: + return "EIDRM"; + case EINPROGRESS: + return "EINPROGRESS"; + case EINTR: + return "EINTR"; + case EINVAL: + return "EINVAL"; + case EIO: + return "EIO"; +#ifdef EISCONN + case EISCONN: + return "EISCONN"; +#endif + case EISDIR: + return "EISDIR"; +#ifdef ELOOP + case ELOOP: + return "ELOOP"; +#endif + case EMFILE: + return "EMFILE"; + case EMLINK: + return "EMLINK"; + case EMSGSIZE: + return "EMSGSIZE"; + case ENAMETOOLONG: + return "ENAMETOOLONG"; + case ENFILE: + return "ENFILE"; + case ENOBUFS: + return "ENOBUFS"; + case ENODEV: + return "ENODEV"; + case ENOENT: + return "ENOENT"; + case ENOEXEC: + return "ENOEXEC"; + case ENOMEM: + return "ENOMEM"; + case ENOSPC: + return "ENOSPC"; + case ENOSYS: + return "ENOSYS"; +#ifdef ENOTCONN + case ENOTCONN: + return "ENOTCONN"; +#endif + case ENOTDIR: + return "ENOTDIR"; +#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */ + case ENOTEMPTY: + return "ENOTEMPTY"; +#endif +#ifdef ENOTSOCK + case ENOTSOCK: + return "ENOTSOCK"; +#endif +#ifdef ENOTSUP + case ENOTSUP: + return "ENOTSUP"; +#endif + case ENOTTY: + return "ENOTTY"; + case ENXIO: + return "ENXIO"; +#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (EOPNOTSUPP != ENOTSUP)) + case EOPNOTSUPP: + return "EOPNOTSUPP"; +#endif +#ifdef EOVERFLOW + case EOVERFLOW: + return "EOVERFLOW"; +#endif + case EPERM: + return "EPERM"; + case EPIPE: + return "EPIPE"; + case EPROTONOSUPPORT: + return "EPROTONOSUPPORT"; + case ERANGE: + return "ERANGE"; +#ifdef EROFS + case EROFS: + return "EROFS"; +#endif + case ESRCH: + return "ESRCH"; +#ifdef ETIMEDOUT + case ETIMEDOUT: + return "ETIMEDOUT"; +#endif +#ifdef ETXTBSY + case ETXTBSY: + return "ETXTBSY"; +#endif +#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) + case EWOULDBLOCK: + return "EWOULDBLOCK"; +#endif + case EXDEV: + return "EXDEV"; + } + + return NULL; +} + + +#ifdef WIN32 + +/* + * Windows' strerror() doesn't know the Winsock codes, so handle them this way + */ +static char * +win32_socket_strerror(int errnum) +{ + static char wserrbuf[256]; + static HANDLE handleDLL = INVALID_HANDLE_VALUE; + + if (handleDLL == INVALID_HANDLE_VALUE) + { + handleDLL = LoadLibraryEx("netmsg.dll", NULL, + DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); + if (handleDLL == NULL) + { + sprintf(wserrbuf, "winsock error %d (could not load netmsg.dll to translate: error code %lu)", + errnum, GetLastError()); + return wserrbuf; + } + } + + ZeroMemory(&wserrbuf, sizeof(wserrbuf)); + if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_FROM_HMODULE, + handleDLL, + errnum, + MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), + wserrbuf, + sizeof(wserrbuf) - 1, + NULL) == 0) + { + /* Failed to get id */ + sprintf(wserrbuf, "unrecognized winsock error %d", errnum); + } + + return wserrbuf; +} + +#endif /* WIN32 */ diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index 6484a67223e..640a4b70d63 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -96,9 +96,10 @@ sub mkvcbuild chklocale.c crypt.c fls.c fseeko.c getrusage.c inet_aton.c random.c srandom.c getaddrinfo.c gettimeofday.c inet_net_ntop.c kill.c open.c erand48.c snprintf.c strlcat.c strlcpy.c dirmod.c noblock.c path.c + dirent.c dlopen.c getopt.c getopt_long.c pg_strong_random.c pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c pqsignal.c mkdtemp.c qsort.c qsort_arg.c quotes.c system.c - sprompt.c tar.c thread.c getopt.c getopt_long.c dirent.c dlopen.c + sprompt.c strerror.c tar.c thread.c win32env.c win32error.c win32security.c win32setlocale.c); push(@pgportfiles, 'rint.c') if ($vsVersion < '12.00'); |