mirror of
https://github.com/curl/curl.git
synced 2026-07-08 05:37:17 +03:00
Windows CE support was limited to successful builds with ming32ce (a toolchain that hasn't seen an update since 2009, using an ancient gcc version and "old mingw"-style SDK headers, that curl deprecated earlier). Builds with MSVC were broken for a long time. mingw32ce builds were never actually tested and runtime and unlikely to work due to missing stubs. Windows CE toolchains also miss to comply with C89. Paired with lack of demand and support for the platform, curl deprecated it earlier. This patch removes support from the codebase to ease maintaining Windows codepaths. Follow-up tof98c0ba834#17924 Follow-up to8491e6574c#17379 Follow-up to2a292c3984#15975 Closes #17927
358 lines
9 KiB
C
358 lines
9 KiB
C
/***************************************************************************
|
|
* _ _ ____ _
|
|
* Project ___| | | | _ \| |
|
|
* / __| | | | |_) | |
|
|
* | (__| |_| | _ <| |___
|
|
* \___|\___/|_| \_\_____|
|
|
*
|
|
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
*
|
|
* This software is licensed as described in the file COPYING, which
|
|
* you should have received as part of this distribution. The terms
|
|
* are also available at https://curl.se/docs/copyright.html.
|
|
*
|
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
|
* copies of the Software, and permit persons to whom the Software is
|
|
* furnished to do so, under the terms of the COPYING file.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
* SPDX-License-Identifier: curl
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "../curl_setup.h"
|
|
|
|
#ifdef HAVE_STRERROR_R
|
|
# if (!defined(HAVE_POSIX_STRERROR_R) && \
|
|
!defined(HAVE_GLIBC_STRERROR_R)) || \
|
|
(defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R))
|
|
# error "strerror_r MUST be either POSIX, glibc style"
|
|
# endif
|
|
#endif
|
|
|
|
#include <curl/curl.h>
|
|
|
|
#ifndef WITHOUT_LIBCURL
|
|
#include <curl/mprintf.h>
|
|
#define SNPRINTF curl_msnprintf
|
|
#else
|
|
/* when built for the test servers */
|
|
|
|
/* adjust for old MSVC */
|
|
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
|
#define SNPRINTF _snprintf
|
|
#else
|
|
#define SNPRINTF snprintf
|
|
#endif
|
|
#endif /* !WITHOUT_LIBCURL */
|
|
|
|
#include "winapi.h"
|
|
#include "strerr.h"
|
|
/* The last 2 #include files should be in this order */
|
|
#include "../curl_memory.h"
|
|
#include "../memdebug.h"
|
|
|
|
#ifdef USE_WINSOCK
|
|
/* This is a helper function for curlx_strerror that converts Winsock error
|
|
* codes (WSAGetLastError) to error messages.
|
|
* Returns NULL if no error message was found for error code.
|
|
*/
|
|
static const char *
|
|
get_winsock_error(int err, char *buf, size_t len)
|
|
{
|
|
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
|
const char *p;
|
|
size_t alen;
|
|
#endif
|
|
|
|
if(!len)
|
|
return NULL;
|
|
|
|
*buf = '\0';
|
|
|
|
#ifdef CURL_DISABLE_VERBOSE_STRINGS
|
|
(void)err;
|
|
return NULL;
|
|
#else
|
|
switch(err) {
|
|
case WSAEINTR:
|
|
p = "Call interrupted";
|
|
break;
|
|
case WSAEBADF:
|
|
p = "Bad file";
|
|
break;
|
|
case WSAEACCES:
|
|
p = "Bad access";
|
|
break;
|
|
case WSAEFAULT:
|
|
p = "Bad argument";
|
|
break;
|
|
case WSAEINVAL:
|
|
p = "Invalid arguments";
|
|
break;
|
|
case WSAEMFILE:
|
|
p = "Out of file descriptors";
|
|
break;
|
|
case WSAEWOULDBLOCK:
|
|
p = "Call would block";
|
|
break;
|
|
case WSAEINPROGRESS:
|
|
case WSAEALREADY:
|
|
p = "Blocking call in progress";
|
|
break;
|
|
case WSAENOTSOCK:
|
|
p = "Descriptor is not a socket";
|
|
break;
|
|
case WSAEDESTADDRREQ:
|
|
p = "Need destination address";
|
|
break;
|
|
case WSAEMSGSIZE:
|
|
p = "Bad message size";
|
|
break;
|
|
case WSAEPROTOTYPE:
|
|
p = "Bad protocol";
|
|
break;
|
|
case WSAENOPROTOOPT:
|
|
p = "Protocol option is unsupported";
|
|
break;
|
|
case WSAEPROTONOSUPPORT:
|
|
p = "Protocol is unsupported";
|
|
break;
|
|
case WSAESOCKTNOSUPPORT:
|
|
p = "Socket is unsupported";
|
|
break;
|
|
case WSAEOPNOTSUPP:
|
|
p = "Operation not supported";
|
|
break;
|
|
case WSAEAFNOSUPPORT:
|
|
p = "Address family not supported";
|
|
break;
|
|
case WSAEPFNOSUPPORT:
|
|
p = "Protocol family not supported";
|
|
break;
|
|
case WSAEADDRINUSE:
|
|
p = "Address already in use";
|
|
break;
|
|
case WSAEADDRNOTAVAIL:
|
|
p = "Address not available";
|
|
break;
|
|
case WSAENETDOWN:
|
|
p = "Network down";
|
|
break;
|
|
case WSAENETUNREACH:
|
|
p = "Network unreachable";
|
|
break;
|
|
case WSAENETRESET:
|
|
p = "Network has been reset";
|
|
break;
|
|
case WSAECONNABORTED:
|
|
p = "Connection was aborted";
|
|
break;
|
|
case WSAECONNRESET:
|
|
p = "Connection was reset";
|
|
break;
|
|
case WSAENOBUFS:
|
|
p = "No buffer space";
|
|
break;
|
|
case WSAEISCONN:
|
|
p = "Socket is already connected";
|
|
break;
|
|
case WSAENOTCONN:
|
|
p = "Socket is not connected";
|
|
break;
|
|
case WSAESHUTDOWN:
|
|
p = "Socket has been shut down";
|
|
break;
|
|
case WSAETOOMANYREFS:
|
|
p = "Too many references";
|
|
break;
|
|
case WSAETIMEDOUT:
|
|
p = "Timed out";
|
|
break;
|
|
case WSAECONNREFUSED:
|
|
p = "Connection refused";
|
|
break;
|
|
case WSAELOOP:
|
|
p = "Loop??";
|
|
break;
|
|
case WSAENAMETOOLONG:
|
|
p = "Name too long";
|
|
break;
|
|
case WSAEHOSTDOWN:
|
|
p = "Host down";
|
|
break;
|
|
case WSAEHOSTUNREACH:
|
|
p = "Host unreachable";
|
|
break;
|
|
case WSAENOTEMPTY:
|
|
p = "Not empty";
|
|
break;
|
|
case WSAEPROCLIM:
|
|
p = "Process limit reached";
|
|
break;
|
|
case WSAEUSERS:
|
|
p = "Too many users";
|
|
break;
|
|
case WSAEDQUOT:
|
|
p = "Bad quota";
|
|
break;
|
|
case WSAESTALE:
|
|
p = "Something is stale";
|
|
break;
|
|
case WSAEREMOTE:
|
|
p = "Remote error";
|
|
break;
|
|
case WSAEDISCON:
|
|
p = "Disconnected";
|
|
break;
|
|
/* Extended Winsock errors */
|
|
case WSASYSNOTREADY:
|
|
p = "Winsock library is not ready";
|
|
break;
|
|
case WSANOTINITIALISED:
|
|
p = "Winsock library not initialised";
|
|
break;
|
|
case WSAVERNOTSUPPORTED:
|
|
p = "Winsock version not supported";
|
|
break;
|
|
|
|
/* getXbyY() errors (already handled in herrmsg):
|
|
* Authoritative Answer: Host not found */
|
|
case WSAHOST_NOT_FOUND:
|
|
p = "Host not found";
|
|
break;
|
|
|
|
/* Non-Authoritative: Host not found, or SERVERFAIL */
|
|
case WSATRY_AGAIN:
|
|
p = "Host not found, try again";
|
|
break;
|
|
|
|
/* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
|
|
case WSANO_RECOVERY:
|
|
p = "Unrecoverable error in call to nameserver";
|
|
break;
|
|
|
|
/* Valid name, no data record of requested type */
|
|
case WSANO_DATA:
|
|
p = "No data record of requested type";
|
|
break;
|
|
|
|
default:
|
|
return NULL;
|
|
}
|
|
alen = strlen(p);
|
|
if(alen < len)
|
|
strcpy(buf, p);
|
|
return buf;
|
|
#endif
|
|
}
|
|
#endif /* USE_WINSOCK */
|
|
|
|
/*
|
|
* Our thread-safe and smart strerror() replacement.
|
|
*
|
|
* The 'err' argument passed in to this function MUST be a true errno number
|
|
* as reported on this system. We do no range checking on the number before
|
|
* we pass it to the "number-to-message" conversion function and there might
|
|
* be systems that do not do proper range checking in there themselves.
|
|
*
|
|
* We do not do range checking (on systems other than Windows) since there is
|
|
* no good reliable and portable way to do it.
|
|
*
|
|
* On Windows different types of error codes overlap. This function has an
|
|
* order of preference when trying to match error codes:
|
|
* CRT (errno), Winsock (WSAGetLastError), Windows API (GetLastError).
|
|
*
|
|
* It may be more correct to call one of the variant functions instead:
|
|
* Call Curl_sspi_strerror if the error code is definitely Windows SSPI.
|
|
* Call curlx_winapi_strerror if the error code is definitely Windows API.
|
|
*/
|
|
const char *curlx_strerror(int err, char *buf, size_t buflen)
|
|
{
|
|
#ifdef _WIN32
|
|
DWORD old_win_err = GetLastError();
|
|
#endif
|
|
int old_errno = errno;
|
|
char *p;
|
|
|
|
if(!buflen)
|
|
return NULL;
|
|
|
|
#ifndef _WIN32
|
|
DEBUGASSERT(err >= 0);
|
|
#endif
|
|
|
|
*buf = '\0';
|
|
|
|
#ifdef _WIN32
|
|
/* 'sys_nerr' is the maximum errno number, it is not widely portable */
|
|
if(err >= 0 && err < sys_nerr)
|
|
SNPRINTF(buf, buflen, "%s", sys_errlist[err]);
|
|
else {
|
|
if(
|
|
#ifdef USE_WINSOCK
|
|
!get_winsock_error(err, buf, buflen) &&
|
|
#endif
|
|
!curlx_get_winapi_error((DWORD)err, buf, buflen))
|
|
SNPRINTF(buf, buflen, "Unknown error %d (%#x)", err, err);
|
|
}
|
|
#else /* !_WIN32 */
|
|
|
|
#if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R)
|
|
/*
|
|
* The POSIX-style strerror_r() may set errno to ERANGE if insufficient
|
|
* storage is supplied via 'strerrbuf' and 'buflen' to hold the generated
|
|
* message string, or EINVAL if 'errnum' is not a valid error number.
|
|
*/
|
|
if(strerror_r(err, buf, buflen) &&
|
|
buflen > sizeof("Unknown error ") + 20) {
|
|
if(buf[0] == '\0')
|
|
SNPRINTF(buf, buflen, "Unknown error %d", err);
|
|
}
|
|
#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
|
|
/*
|
|
* The glibc-style strerror_r() only *might* use the buffer we pass to
|
|
* the function, but it always returns the error message as a pointer,
|
|
* so we must copy that string unconditionally (if non-NULL).
|
|
*/
|
|
{
|
|
char buffer[256];
|
|
char *msg = strerror_r(err, buffer, sizeof(buffer));
|
|
if(msg && buflen > 1)
|
|
SNPRINTF(buf, buflen, "%s", msg);
|
|
else if(buflen > sizeof("Unknown error ") + 20)
|
|
SNPRINTF(buf, buflen, "Unknown error %d", err);
|
|
}
|
|
#else
|
|
{
|
|
/* !checksrc! disable BANNEDFUNC 1 */
|
|
const char *msg = strerror(err);
|
|
if(msg && buflen > 1)
|
|
SNPRINTF(buf, buflen, "%s", msg);
|
|
else if(buflen > sizeof("Unknown error ") + 20)
|
|
SNPRINTF(buf, buflen, "Unknown error %d", err);
|
|
}
|
|
#endif
|
|
|
|
#endif /* _WIN32 */
|
|
|
|
/* strip trailing '\r\n' or '\n'. */
|
|
p = strrchr(buf, '\n');
|
|
if(p && (p - buf) >= 2)
|
|
*p = '\0';
|
|
p = strrchr(buf, '\r');
|
|
if(p && (p - buf) >= 1)
|
|
*p = '\0';
|
|
|
|
if(errno != old_errno)
|
|
errno = old_errno;
|
|
|
|
#ifdef _WIN32
|
|
if(old_win_err != GetLastError())
|
|
SetLastError(old_win_err);
|
|
#endif
|
|
|
|
return buf;
|
|
}
|