quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

strerror.c (25884B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  * SPDX-License-Identifier: curl
     22  *
     23  ***************************************************************************/
     24 
     25 #include "curl_setup.h"
     26 
     27 #ifdef HAVE_STRERROR_R
     28 #  if (!defined(HAVE_POSIX_STRERROR_R) && \
     29        !defined(HAVE_GLIBC_STRERROR_R)) || \
     30       (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R))
     31 #    error "strerror_r MUST be either POSIX, glibc style"
     32 #  endif
     33 #endif
     34 
     35 #include <curl/curl.h>
     36 
     37 #ifdef USE_LIBIDN2
     38 #include <idn2.h>
     39 #endif
     40 
     41 #ifdef USE_WINDOWS_SSPI
     42 #include "curl_sspi.h"
     43 #endif
     44 
     45 #include "curlx/winapi.h"
     46 #include "strerror.h"
     47 /* The last 3 #include files should be in this order */
     48 #include "curl_printf.h"
     49 #include "curl_memory.h"
     50 #include "memdebug.h"
     51 
     52 const char *
     53 curl_easy_strerror(CURLcode error)
     54 {
     55 #ifndef CURL_DISABLE_VERBOSE_STRINGS
     56   switch(error) {
     57   case CURLE_OK:
     58     return "No error";
     59 
     60   case CURLE_UNSUPPORTED_PROTOCOL:
     61     return "Unsupported protocol";
     62 
     63   case CURLE_FAILED_INIT:
     64     return "Failed initialization";
     65 
     66   case CURLE_URL_MALFORMAT:
     67     return "URL using bad/illegal format or missing URL";
     68 
     69   case CURLE_NOT_BUILT_IN:
     70     return "A requested feature, protocol or option was not found built-in in"
     71       " this libcurl due to a build-time decision.";
     72 
     73   case CURLE_COULDNT_RESOLVE_PROXY:
     74     return "Could not resolve proxy name";
     75 
     76   case CURLE_COULDNT_RESOLVE_HOST:
     77     return "Could not resolve hostname";
     78 
     79   case CURLE_COULDNT_CONNECT:
     80     return "Could not connect to server";
     81 
     82   case CURLE_WEIRD_SERVER_REPLY:
     83     return "Weird server reply";
     84 
     85   case CURLE_REMOTE_ACCESS_DENIED:
     86     return "Access denied to remote resource";
     87 
     88   case CURLE_FTP_ACCEPT_FAILED:
     89     return "FTP: The server failed to connect to data port";
     90 
     91   case CURLE_FTP_ACCEPT_TIMEOUT:
     92     return "FTP: Accepting server connect has timed out";
     93 
     94   case CURLE_FTP_PRET_FAILED:
     95     return "FTP: The server did not accept the PRET command.";
     96 
     97   case CURLE_FTP_WEIRD_PASS_REPLY:
     98     return "FTP: unknown PASS reply";
     99 
    100   case CURLE_FTP_WEIRD_PASV_REPLY:
    101     return "FTP: unknown PASV reply";
    102 
    103   case CURLE_FTP_WEIRD_227_FORMAT:
    104     return "FTP: unknown 227 response format";
    105 
    106   case CURLE_FTP_CANT_GET_HOST:
    107     return "FTP: cannot figure out the host in the PASV response";
    108 
    109   case CURLE_HTTP2:
    110     return "Error in the HTTP2 framing layer";
    111 
    112   case CURLE_FTP_COULDNT_SET_TYPE:
    113     return "FTP: could not set file type";
    114 
    115   case CURLE_PARTIAL_FILE:
    116     return "Transferred a partial file";
    117 
    118   case CURLE_FTP_COULDNT_RETR_FILE:
    119     return "FTP: could not retrieve (RETR failed) the specified file";
    120 
    121   case CURLE_QUOTE_ERROR:
    122     return "Quote command returned error";
    123 
    124   case CURLE_HTTP_RETURNED_ERROR:
    125     return "HTTP response code said error";
    126 
    127   case CURLE_WRITE_ERROR:
    128     return "Failed writing received data to disk/application";
    129 
    130   case CURLE_UPLOAD_FAILED:
    131     return "Upload failed (at start/before it took off)";
    132 
    133   case CURLE_READ_ERROR:
    134     return "Failed to open/read local data from file/application";
    135 
    136   case CURLE_OUT_OF_MEMORY:
    137     return "Out of memory";
    138 
    139   case CURLE_OPERATION_TIMEDOUT:
    140     return "Timeout was reached";
    141 
    142   case CURLE_FTP_PORT_FAILED:
    143     return "FTP: command PORT failed";
    144 
    145   case CURLE_FTP_COULDNT_USE_REST:
    146     return "FTP: command REST failed";
    147 
    148   case CURLE_RANGE_ERROR:
    149     return "Requested range was not delivered by the server";
    150 
    151   case CURLE_SSL_CONNECT_ERROR:
    152     return "SSL connect error";
    153 
    154   case CURLE_BAD_DOWNLOAD_RESUME:
    155     return "Could not resume download";
    156 
    157   case CURLE_FILE_COULDNT_READ_FILE:
    158     return "Could not read a file:// file";
    159 
    160   case CURLE_LDAP_CANNOT_BIND:
    161     return "LDAP: cannot bind";
    162 
    163   case CURLE_LDAP_SEARCH_FAILED:
    164     return "LDAP: search failed";
    165 
    166   case CURLE_ABORTED_BY_CALLBACK:
    167     return "Operation was aborted by an application callback";
    168 
    169   case CURLE_BAD_FUNCTION_ARGUMENT:
    170     return "A libcurl function was given a bad argument";
    171 
    172   case CURLE_INTERFACE_FAILED:
    173     return "Failed binding local connection end";
    174 
    175   case CURLE_TOO_MANY_REDIRECTS:
    176     return "Number of redirects hit maximum amount";
    177 
    178   case CURLE_UNKNOWN_OPTION:
    179     return "An unknown option was passed in to libcurl";
    180 
    181   case CURLE_SETOPT_OPTION_SYNTAX:
    182     return "Malformed option provided in a setopt";
    183 
    184   case CURLE_GOT_NOTHING:
    185     return "Server returned nothing (no headers, no data)";
    186 
    187   case CURLE_SSL_ENGINE_NOTFOUND:
    188     return "SSL crypto engine not found";
    189 
    190   case CURLE_SSL_ENGINE_SETFAILED:
    191     return "Can not set SSL crypto engine as default";
    192 
    193   case CURLE_SSL_ENGINE_INITFAILED:
    194     return "Failed to initialise SSL crypto engine";
    195 
    196   case CURLE_SEND_ERROR:
    197     return "Failed sending data to the peer";
    198 
    199   case CURLE_RECV_ERROR:
    200     return "Failure when receiving data from the peer";
    201 
    202   case CURLE_SSL_CERTPROBLEM:
    203     return "Problem with the local SSL certificate";
    204 
    205   case CURLE_SSL_CIPHER:
    206     return "Could not use specified SSL cipher";
    207 
    208   case CURLE_PEER_FAILED_VERIFICATION:
    209     return "SSL peer certificate or SSH remote key was not OK";
    210 
    211   case CURLE_SSL_CACERT_BADFILE:
    212     return "Problem with the SSL CA cert (path? access rights?)";
    213 
    214   case CURLE_BAD_CONTENT_ENCODING:
    215     return "Unrecognized or bad HTTP Content or Transfer-Encoding";
    216 
    217   case CURLE_FILESIZE_EXCEEDED:
    218     return "Maximum file size exceeded";
    219 
    220   case CURLE_USE_SSL_FAILED:
    221     return "Requested SSL level failed";
    222 
    223   case CURLE_SSL_SHUTDOWN_FAILED:
    224     return "Failed to shut down the SSL connection";
    225 
    226   case CURLE_SSL_CRL_BADFILE:
    227     return "Failed to load CRL file (path? access rights?, format?)";
    228 
    229   case CURLE_SSL_ISSUER_ERROR:
    230     return "Issuer check against peer certificate failed";
    231 
    232   case CURLE_SEND_FAIL_REWIND:
    233     return "Send failed since rewinding of the data stream failed";
    234 
    235   case CURLE_LOGIN_DENIED:
    236     return "Login denied";
    237 
    238   case CURLE_TFTP_NOTFOUND:
    239     return "TFTP: File Not Found";
    240 
    241   case CURLE_TFTP_PERM:
    242     return "TFTP: Access Violation";
    243 
    244   case CURLE_REMOTE_DISK_FULL:
    245     return "Disk full or allocation exceeded";
    246 
    247   case CURLE_TFTP_ILLEGAL:
    248     return "TFTP: Illegal operation";
    249 
    250   case CURLE_TFTP_UNKNOWNID:
    251     return "TFTP: Unknown transfer ID";
    252 
    253   case CURLE_REMOTE_FILE_EXISTS:
    254     return "Remote file already exists";
    255 
    256   case CURLE_TFTP_NOSUCHUSER:
    257     return "TFTP: No such user";
    258 
    259   case CURLE_REMOTE_FILE_NOT_FOUND:
    260     return "Remote file not found";
    261 
    262   case CURLE_SSH:
    263     return "Error in the SSH layer";
    264 
    265   case CURLE_AGAIN:
    266     return "Socket not ready for send/recv";
    267 
    268   case CURLE_RTSP_CSEQ_ERROR:
    269     return "RTSP CSeq mismatch or invalid CSeq";
    270 
    271   case CURLE_RTSP_SESSION_ERROR:
    272     return "RTSP session error";
    273 
    274   case CURLE_FTP_BAD_FILE_LIST:
    275     return "Unable to parse FTP file list";
    276 
    277   case CURLE_CHUNK_FAILED:
    278     return "Chunk callback failed";
    279 
    280   case CURLE_NO_CONNECTION_AVAILABLE:
    281     return "The max connection limit is reached";
    282 
    283   case CURLE_SSL_PINNEDPUBKEYNOTMATCH:
    284     return "SSL public key does not match pinned public key";
    285 
    286   case CURLE_SSL_INVALIDCERTSTATUS:
    287     return "SSL server certificate status verification FAILED";
    288 
    289   case CURLE_HTTP2_STREAM:
    290     return "Stream error in the HTTP/2 framing layer";
    291 
    292   case CURLE_RECURSIVE_API_CALL:
    293     return "API function called from within callback";
    294 
    295   case CURLE_AUTH_ERROR:
    296     return "An authentication function returned an error";
    297 
    298   case CURLE_HTTP3:
    299     return "HTTP/3 error";
    300 
    301   case CURLE_QUIC_CONNECT_ERROR:
    302     return "QUIC connection error";
    303 
    304   case CURLE_PROXY:
    305     return "proxy handshake error";
    306 
    307   case CURLE_SSL_CLIENTCERT:
    308     return "SSL Client Certificate required";
    309 
    310   case CURLE_UNRECOVERABLE_POLL:
    311     return "Unrecoverable error in select/poll";
    312 
    313   case CURLE_TOO_LARGE:
    314     return "A value or data field grew larger than allowed";
    315 
    316   case CURLE_ECH_REQUIRED:
    317     return "ECH attempted but failed";
    318 
    319     /* error codes not used by current libcurl */
    320   default:
    321     break;
    322   }
    323   /*
    324    * By using a switch, gcc -Wall will complain about enum values
    325    * which do not appear, helping keep this function up-to-date.
    326    * By using gcc -Wall -Werror, you cannot forget.
    327    *
    328    * A table would not have the same benefit. Most compilers will generate
    329    * code similar to a table in any case, so there is little performance gain
    330    * from a table. Something is broken for the user's application, anyways, so
    331    * does it matter how fast it _does not_ work?
    332    *
    333    * The line number for the error will be near this comment, which is why it
    334    * is here, and not at the start of the switch.
    335    */
    336   return "Unknown error";
    337 #else
    338   if(!error)
    339     return "No error";
    340   else
    341     return "Error";
    342 #endif
    343 }
    344 
    345 const char *
    346 curl_multi_strerror(CURLMcode error)
    347 {
    348 #ifndef CURL_DISABLE_VERBOSE_STRINGS
    349   switch(error) {
    350   case CURLM_CALL_MULTI_PERFORM:
    351     return "Please call curl_multi_perform() soon";
    352 
    353   case CURLM_OK:
    354     return "No error";
    355 
    356   case CURLM_BAD_HANDLE:
    357     return "Invalid multi handle";
    358 
    359   case CURLM_BAD_EASY_HANDLE:
    360     return "Invalid easy handle";
    361 
    362   case CURLM_OUT_OF_MEMORY:
    363     return "Out of memory";
    364 
    365   case CURLM_INTERNAL_ERROR:
    366     return "Internal error";
    367 
    368   case CURLM_BAD_SOCKET:
    369     return "Invalid socket argument";
    370 
    371   case CURLM_UNKNOWN_OPTION:
    372     return "Unknown option";
    373 
    374   case CURLM_ADDED_ALREADY:
    375     return "The easy handle is already added to a multi handle";
    376 
    377   case CURLM_RECURSIVE_API_CALL:
    378     return "API function called from within callback";
    379 
    380   case CURLM_WAKEUP_FAILURE:
    381     return "Wakeup is unavailable or failed";
    382 
    383   case CURLM_BAD_FUNCTION_ARGUMENT:
    384     return "A libcurl function was given a bad argument";
    385 
    386   case CURLM_ABORTED_BY_CALLBACK:
    387     return "Operation was aborted by an application callback";
    388 
    389   case CURLM_UNRECOVERABLE_POLL:
    390     return "Unrecoverable error in select/poll";
    391 
    392   case CURLM_LAST:
    393     break;
    394   }
    395 
    396   return "Unknown error";
    397 #else
    398   if(error == CURLM_OK)
    399     return "No error";
    400   else
    401     return "Error";
    402 #endif
    403 }
    404 
    405 const char *
    406 curl_share_strerror(CURLSHcode error)
    407 {
    408 #ifndef CURL_DISABLE_VERBOSE_STRINGS
    409   switch(error) {
    410   case CURLSHE_OK:
    411     return "No error";
    412 
    413   case CURLSHE_BAD_OPTION:
    414     return "Unknown share option";
    415 
    416   case CURLSHE_IN_USE:
    417     return "Share currently in use";
    418 
    419   case CURLSHE_INVALID:
    420     return "Invalid share handle";
    421 
    422   case CURLSHE_NOMEM:
    423     return "Out of memory";
    424 
    425   case CURLSHE_NOT_BUILT_IN:
    426     return "Feature not enabled in this library";
    427 
    428   case CURLSHE_LAST:
    429     break;
    430   }
    431 
    432   return "CURLSHcode unknown";
    433 #else
    434   if(error == CURLSHE_OK)
    435     return "No error";
    436   else
    437     return "Error";
    438 #endif
    439 }
    440 
    441 const char *
    442 curl_url_strerror(CURLUcode error)
    443 {
    444 #ifndef CURL_DISABLE_VERBOSE_STRINGS
    445   switch(error) {
    446   case CURLUE_OK:
    447     return "No error";
    448 
    449   case CURLUE_BAD_HANDLE:
    450     return "An invalid CURLU pointer was passed as argument";
    451 
    452   case CURLUE_BAD_PARTPOINTER:
    453     return "An invalid 'part' argument was passed as argument";
    454 
    455   case CURLUE_MALFORMED_INPUT:
    456     return "Malformed input to a URL function";
    457 
    458   case CURLUE_BAD_PORT_NUMBER:
    459     return "Port number was not a decimal number between 0 and 65535";
    460 
    461   case CURLUE_UNSUPPORTED_SCHEME:
    462     return "Unsupported URL scheme";
    463 
    464   case CURLUE_URLDECODE:
    465     return "URL decode error, most likely because of rubbish in the input";
    466 
    467   case CURLUE_OUT_OF_MEMORY:
    468     return "A memory function failed";
    469 
    470   case CURLUE_USER_NOT_ALLOWED:
    471     return "Credentials was passed in the URL when prohibited";
    472 
    473   case CURLUE_UNKNOWN_PART:
    474     return "An unknown part ID was passed to a URL API function";
    475 
    476   case CURLUE_NO_SCHEME:
    477     return "No scheme part in the URL";
    478 
    479   case CURLUE_NO_USER:
    480     return "No user part in the URL";
    481 
    482   case CURLUE_NO_PASSWORD:
    483     return "No password part in the URL";
    484 
    485   case CURLUE_NO_OPTIONS:
    486     return "No options part in the URL";
    487 
    488   case CURLUE_NO_HOST:
    489     return "No host part in the URL";
    490 
    491   case CURLUE_NO_PORT:
    492     return "No port part in the URL";
    493 
    494   case CURLUE_NO_QUERY:
    495     return "No query part in the URL";
    496 
    497   case CURLUE_NO_FRAGMENT:
    498     return "No fragment part in the URL";
    499 
    500   case CURLUE_NO_ZONEID:
    501     return "No zoneid part in the URL";
    502 
    503   case CURLUE_BAD_LOGIN:
    504     return "Bad login part";
    505 
    506   case CURLUE_BAD_IPV6:
    507     return "Bad IPv6 address";
    508 
    509   case CURLUE_BAD_HOSTNAME:
    510     return "Bad hostname";
    511 
    512   case CURLUE_BAD_FILE_URL:
    513     return "Bad file:// URL";
    514 
    515   case CURLUE_BAD_SLASHES:
    516     return "Unsupported number of slashes following scheme";
    517 
    518   case CURLUE_BAD_SCHEME:
    519     return "Bad scheme";
    520 
    521   case CURLUE_BAD_PATH:
    522     return "Bad path";
    523 
    524   case CURLUE_BAD_FRAGMENT:
    525     return "Bad fragment";
    526 
    527   case CURLUE_BAD_QUERY:
    528     return "Bad query";
    529 
    530   case CURLUE_BAD_PASSWORD:
    531     return "Bad password";
    532 
    533   case CURLUE_BAD_USER:
    534     return "Bad user";
    535 
    536   case CURLUE_LACKS_IDN:
    537     return "libcurl lacks IDN support";
    538 
    539   case CURLUE_TOO_LARGE:
    540     return "A value or data field is larger than allowed";
    541 
    542   case CURLUE_LAST:
    543     break;
    544   }
    545 
    546   return "CURLUcode unknown";
    547 #else
    548   if(error == CURLUE_OK)
    549     return "No error";
    550   else
    551     return "Error";
    552 #endif
    553 }
    554 
    555 #ifdef USE_WINSOCK
    556 /* This is a helper function for Curl_strerror that converts Winsock error
    557  * codes (WSAGetLastError) to error messages.
    558  * Returns NULL if no error message was found for error code.
    559  */
    560 static const char *
    561 get_winsock_error(int err, char *buf, size_t len)
    562 {
    563 #ifndef CURL_DISABLE_VERBOSE_STRINGS
    564   const char *p;
    565   size_t alen;
    566 #endif
    567 
    568   if(!len)
    569     return NULL;
    570 
    571   *buf = '\0';
    572 
    573 #ifdef CURL_DISABLE_VERBOSE_STRINGS
    574   (void)err;
    575   return NULL;
    576 #else
    577   switch(err) {
    578   case WSAEINTR:
    579     p = "Call interrupted";
    580     break;
    581   case WSAEBADF:
    582     p = "Bad file";
    583     break;
    584   case WSAEACCES:
    585     p = "Bad access";
    586     break;
    587   case WSAEFAULT:
    588     p = "Bad argument";
    589     break;
    590   case WSAEINVAL:
    591     p = "Invalid arguments";
    592     break;
    593   case WSAEMFILE:
    594     p = "Out of file descriptors";
    595     break;
    596   case WSAEWOULDBLOCK:
    597     p = "Call would block";
    598     break;
    599   case WSAEINPROGRESS:
    600   case WSAEALREADY:
    601     p = "Blocking call in progress";
    602     break;
    603   case WSAENOTSOCK:
    604     p = "Descriptor is not a socket";
    605     break;
    606   case WSAEDESTADDRREQ:
    607     p = "Need destination address";
    608     break;
    609   case WSAEMSGSIZE:
    610     p = "Bad message size";
    611     break;
    612   case WSAEPROTOTYPE:
    613     p = "Bad protocol";
    614     break;
    615   case WSAENOPROTOOPT:
    616     p = "Protocol option is unsupported";
    617     break;
    618   case WSAEPROTONOSUPPORT:
    619     p = "Protocol is unsupported";
    620     break;
    621   case WSAESOCKTNOSUPPORT:
    622     p = "Socket is unsupported";
    623     break;
    624   case WSAEOPNOTSUPP:
    625     p = "Operation not supported";
    626     break;
    627   case WSAEAFNOSUPPORT:
    628     p = "Address family not supported";
    629     break;
    630   case WSAEPFNOSUPPORT:
    631     p = "Protocol family not supported";
    632     break;
    633   case WSAEADDRINUSE:
    634     p = "Address already in use";
    635     break;
    636   case WSAEADDRNOTAVAIL:
    637     p = "Address not available";
    638     break;
    639   case WSAENETDOWN:
    640     p = "Network down";
    641     break;
    642   case WSAENETUNREACH:
    643     p = "Network unreachable";
    644     break;
    645   case WSAENETRESET:
    646     p = "Network has been reset";
    647     break;
    648   case WSAECONNABORTED:
    649     p = "Connection was aborted";
    650     break;
    651   case WSAECONNRESET:
    652     p = "Connection was reset";
    653     break;
    654   case WSAENOBUFS:
    655     p = "No buffer space";
    656     break;
    657   case WSAEISCONN:
    658     p = "Socket is already connected";
    659     break;
    660   case WSAENOTCONN:
    661     p = "Socket is not connected";
    662     break;
    663   case WSAESHUTDOWN:
    664     p = "Socket has been shut down";
    665     break;
    666   case WSAETOOMANYREFS:
    667     p = "Too many references";
    668     break;
    669   case WSAETIMEDOUT:
    670     p = "Timed out";
    671     break;
    672   case WSAECONNREFUSED:
    673     p = "Connection refused";
    674     break;
    675   case WSAELOOP:
    676     p = "Loop??";
    677     break;
    678   case WSAENAMETOOLONG:
    679     p = "Name too long";
    680     break;
    681   case WSAEHOSTDOWN:
    682     p = "Host down";
    683     break;
    684   case WSAEHOSTUNREACH:
    685     p = "Host unreachable";
    686     break;
    687   case WSAENOTEMPTY:
    688     p = "Not empty";
    689     break;
    690   case WSAEPROCLIM:
    691     p = "Process limit reached";
    692     break;
    693   case WSAEUSERS:
    694     p = "Too many users";
    695     break;
    696   case WSAEDQUOT:
    697     p = "Bad quota";
    698     break;
    699   case WSAESTALE:
    700     p = "Something is stale";
    701     break;
    702   case WSAEREMOTE:
    703     p = "Remote error";
    704     break;
    705 #ifdef WSAEDISCON  /* missing in SalfordC! */
    706   case WSAEDISCON:
    707     p = "Disconnected";
    708     break;
    709 #endif
    710     /* Extended Winsock errors */
    711   case WSASYSNOTREADY:
    712     p = "Winsock library is not ready";
    713     break;
    714   case WSANOTINITIALISED:
    715     p = "Winsock library not initialised";
    716     break;
    717   case WSAVERNOTSUPPORTED:
    718     p = "Winsock version not supported";
    719     break;
    720 
    721     /* getXbyY() errors (already handled in herrmsg):
    722      * Authoritative Answer: Host not found */
    723   case WSAHOST_NOT_FOUND:
    724     p = "Host not found";
    725     break;
    726 
    727     /* Non-Authoritative: Host not found, or SERVERFAIL */
    728   case WSATRY_AGAIN:
    729     p = "Host not found, try again";
    730     break;
    731 
    732     /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
    733   case WSANO_RECOVERY:
    734     p = "Unrecoverable error in call to nameserver";
    735     break;
    736 
    737     /* Valid name, no data record of requested type */
    738   case WSANO_DATA:
    739     p = "No data record of requested type";
    740     break;
    741 
    742   default:
    743     return NULL;
    744   }
    745   alen = strlen(p);
    746   if(alen < len)
    747     strcpy(buf, p);
    748   return buf;
    749 #endif
    750 }
    751 #endif   /* USE_WINSOCK */
    752 
    753 /*
    754  * Our thread-safe and smart strerror() replacement.
    755  *
    756  * The 'err' argument passed in to this function MUST be a true errno number
    757  * as reported on this system. We do no range checking on the number before
    758  * we pass it to the "number-to-message" conversion function and there might
    759  * be systems that do not do proper range checking in there themselves.
    760  *
    761  * We do not do range checking (on systems other than Windows) since there is
    762  * no good reliable and portable way to do it.
    763  *
    764  * On Windows different types of error codes overlap. This function has an
    765  * order of preference when trying to match error codes:
    766  * CRT (errno), Winsock (WSAGetLastError), Windows API (GetLastError).
    767  *
    768  * It may be more correct to call one of the variant functions instead:
    769  * Call Curl_sspi_strerror if the error code is definitely Windows SSPI.
    770  * Call curlx_winapi_strerror if the error code is definitely Windows API.
    771  */
    772 const char *Curl_strerror(int err, char *buf, size_t buflen)
    773 {
    774 #ifdef _WIN32
    775   DWORD old_win_err = GetLastError();
    776 #endif
    777   int old_errno = errno;
    778   char *p;
    779 
    780   if(!buflen)
    781     return NULL;
    782 
    783 #ifndef _WIN32
    784   DEBUGASSERT(err >= 0);
    785 #endif
    786 
    787   *buf = '\0';
    788 
    789 #ifdef _WIN32
    790 #ifndef UNDER_CE
    791   /* 'sys_nerr' is the maximum errno number, it is not widely portable */
    792   if(err >= 0 && err < sys_nerr)
    793     curl_msnprintf(buf, buflen, "%s", sys_errlist[err]);
    794   else
    795 #endif
    796   {
    797     if(
    798 #ifdef USE_WINSOCK
    799       !get_winsock_error(err, buf, buflen) &&
    800 #endif
    801       !curlx_get_winapi_error(err, buf, buflen))
    802       curl_msnprintf(buf, buflen, "Unknown error %d (%#x)", err, err);
    803   }
    804 #else /* not Windows coming up */
    805 
    806 #if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R)
    807  /*
    808   * The POSIX-style strerror_r() may set errno to ERANGE if insufficient
    809   * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated
    810   * message string, or EINVAL if 'errnum' is not a valid error number.
    811   */
    812   if(0 != strerror_r(err, buf, buflen)) {
    813     if('\0' == buf[0])
    814       curl_msnprintf(buf, buflen, "Unknown error %d", err);
    815   }
    816 #elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
    817  /*
    818   * The glibc-style strerror_r() only *might* use the buffer we pass to
    819   * the function, but it always returns the error message as a pointer,
    820   * so we must copy that string unconditionally (if non-NULL).
    821   */
    822   {
    823     char buffer[256];
    824     char *msg = strerror_r(err, buffer, sizeof(buffer));
    825     if(msg)
    826       curl_msnprintf(buf, buflen, "%s", msg);
    827     else
    828       curl_msnprintf(buf, buflen, "Unknown error %d", err);
    829   }
    830 #else
    831   {
    832     /* !checksrc! disable BANNEDFUNC 1 */
    833     const char *msg = strerror(err);
    834     if(msg)
    835       curl_msnprintf(buf, buflen, "%s", msg);
    836     else
    837       curl_msnprintf(buf, buflen, "Unknown error %d", err);
    838   }
    839 #endif
    840 
    841 #endif /* end of not Windows */
    842 
    843   /* strip trailing '\r\n' or '\n'. */
    844   p = strrchr(buf, '\n');
    845   if(p && (p - buf) >= 2)
    846     *p = '\0';
    847   p = strrchr(buf, '\r');
    848   if(p && (p - buf) >= 1)
    849     *p = '\0';
    850 
    851   if(errno != old_errno)
    852     CURL_SETERRNO(old_errno);
    853 
    854 #ifdef _WIN32
    855   if(old_win_err != GetLastError())
    856     SetLastError(old_win_err);
    857 #endif
    858 
    859   return buf;
    860 }
    861 
    862 #ifdef USE_WINDOWS_SSPI
    863 /*
    864  * Curl_sspi_strerror:
    865  * Variant of Curl_strerror if the error code is definitely Windows SSPI.
    866  */
    867 const char *Curl_sspi_strerror(int err, char *buf, size_t buflen)
    868 {
    869 #ifdef _WIN32
    870   DWORD old_win_err = GetLastError();
    871 #endif
    872   int old_errno = errno;
    873   const char *txt;
    874 
    875   if(!buflen)
    876     return NULL;
    877 
    878   *buf = '\0';
    879 
    880 #ifndef CURL_DISABLE_VERBOSE_STRINGS
    881 
    882   switch(err) {
    883     case SEC_E_OK:
    884       txt = "No error";
    885       break;
    886 #define SEC2TXT(sec) case sec: txt = #sec; break
    887     SEC2TXT(CRYPT_E_REVOKED);
    888     SEC2TXT(CRYPT_E_NO_REVOCATION_DLL);
    889     SEC2TXT(CRYPT_E_NO_REVOCATION_CHECK);
    890     SEC2TXT(CRYPT_E_REVOCATION_OFFLINE);
    891     SEC2TXT(CRYPT_E_NOT_IN_REVOCATION_DATABASE);
    892     SEC2TXT(SEC_E_ALGORITHM_MISMATCH);
    893     SEC2TXT(SEC_E_BAD_BINDINGS);
    894     SEC2TXT(SEC_E_BAD_PKGID);
    895     SEC2TXT(SEC_E_BUFFER_TOO_SMALL);
    896     SEC2TXT(SEC_E_CANNOT_INSTALL);
    897     SEC2TXT(SEC_E_CANNOT_PACK);
    898     SEC2TXT(SEC_E_CERT_EXPIRED);
    899     SEC2TXT(SEC_E_CERT_UNKNOWN);
    900     SEC2TXT(SEC_E_CERT_WRONG_USAGE);
    901     SEC2TXT(SEC_E_CONTEXT_EXPIRED);
    902     SEC2TXT(SEC_E_CROSSREALM_DELEGATION_FAILURE);
    903     SEC2TXT(SEC_E_CRYPTO_SYSTEM_INVALID);
    904     SEC2TXT(SEC_E_DECRYPT_FAILURE);
    905     SEC2TXT(SEC_E_DELEGATION_POLICY);
    906     SEC2TXT(SEC_E_DELEGATION_REQUIRED);
    907     SEC2TXT(SEC_E_DOWNGRADE_DETECTED);
    908     SEC2TXT(SEC_E_ENCRYPT_FAILURE);
    909     SEC2TXT(SEC_E_ILLEGAL_MESSAGE);
    910     SEC2TXT(SEC_E_INCOMPLETE_CREDENTIALS);
    911     SEC2TXT(SEC_E_INCOMPLETE_MESSAGE);
    912     SEC2TXT(SEC_E_INSUFFICIENT_MEMORY);
    913     SEC2TXT(SEC_E_INTERNAL_ERROR);
    914     SEC2TXT(SEC_E_INVALID_HANDLE);
    915     SEC2TXT(SEC_E_INVALID_PARAMETER);
    916     SEC2TXT(SEC_E_INVALID_TOKEN);
    917     SEC2TXT(SEC_E_ISSUING_CA_UNTRUSTED);
    918     SEC2TXT(SEC_E_ISSUING_CA_UNTRUSTED_KDC);
    919     SEC2TXT(SEC_E_KDC_CERT_EXPIRED);
    920     SEC2TXT(SEC_E_KDC_CERT_REVOKED);
    921     SEC2TXT(SEC_E_KDC_INVALID_REQUEST);
    922     SEC2TXT(SEC_E_KDC_UNABLE_TO_REFER);
    923     SEC2TXT(SEC_E_KDC_UNKNOWN_ETYPE);
    924     SEC2TXT(SEC_E_LOGON_DENIED);
    925     SEC2TXT(SEC_E_MAX_REFERRALS_EXCEEDED);
    926     SEC2TXT(SEC_E_MESSAGE_ALTERED);
    927     SEC2TXT(SEC_E_MULTIPLE_ACCOUNTS);
    928     SEC2TXT(SEC_E_MUST_BE_KDC);
    929     SEC2TXT(SEC_E_NOT_OWNER);
    930     SEC2TXT(SEC_E_NO_AUTHENTICATING_AUTHORITY);
    931     SEC2TXT(SEC_E_NO_CREDENTIALS);
    932     SEC2TXT(SEC_E_NO_IMPERSONATION);
    933     SEC2TXT(SEC_E_NO_IP_ADDRESSES);
    934     SEC2TXT(SEC_E_NO_KERB_KEY);
    935     SEC2TXT(SEC_E_NO_PA_DATA);
    936     SEC2TXT(SEC_E_NO_S4U_PROT_SUPPORT);
    937     SEC2TXT(SEC_E_NO_TGT_REPLY);
    938     SEC2TXT(SEC_E_OUT_OF_SEQUENCE);
    939     SEC2TXT(SEC_E_PKINIT_CLIENT_FAILURE);
    940     SEC2TXT(SEC_E_PKINIT_NAME_MISMATCH);
    941     SEC2TXT(SEC_E_POLICY_NLTM_ONLY);
    942     SEC2TXT(SEC_E_QOP_NOT_SUPPORTED);
    943     SEC2TXT(SEC_E_REVOCATION_OFFLINE_C);
    944     SEC2TXT(SEC_E_REVOCATION_OFFLINE_KDC);
    945     SEC2TXT(SEC_E_SECPKG_NOT_FOUND);
    946     SEC2TXT(SEC_E_SECURITY_QOS_FAILED);
    947     SEC2TXT(SEC_E_SHUTDOWN_IN_PROGRESS);
    948     SEC2TXT(SEC_E_SMARTCARD_CERT_EXPIRED);
    949     SEC2TXT(SEC_E_SMARTCARD_CERT_REVOKED);
    950     SEC2TXT(SEC_E_SMARTCARD_LOGON_REQUIRED);
    951     SEC2TXT(SEC_E_STRONG_CRYPTO_NOT_SUPPORTED);
    952     SEC2TXT(SEC_E_TARGET_UNKNOWN);
    953     SEC2TXT(SEC_E_TIME_SKEW);
    954     SEC2TXT(SEC_E_TOO_MANY_PRINCIPALS);
    955     SEC2TXT(SEC_E_UNFINISHED_CONTEXT_DELETED);
    956     SEC2TXT(SEC_E_UNKNOWN_CREDENTIALS);
    957     SEC2TXT(SEC_E_UNSUPPORTED_FUNCTION);
    958     SEC2TXT(SEC_E_UNSUPPORTED_PREAUTH);
    959     SEC2TXT(SEC_E_UNTRUSTED_ROOT);
    960     SEC2TXT(SEC_E_WRONG_CREDENTIAL_HANDLE);
    961     SEC2TXT(SEC_E_WRONG_PRINCIPAL);
    962     SEC2TXT(SEC_I_COMPLETE_AND_CONTINUE);
    963     SEC2TXT(SEC_I_COMPLETE_NEEDED);
    964     SEC2TXT(SEC_I_CONTEXT_EXPIRED);
    965     SEC2TXT(SEC_I_CONTINUE_NEEDED);
    966     SEC2TXT(SEC_I_INCOMPLETE_CREDENTIALS);
    967     SEC2TXT(SEC_I_LOCAL_LOGON);
    968     SEC2TXT(SEC_I_NO_LSA_CONTEXT);
    969     SEC2TXT(SEC_I_RENEGOTIATE);
    970     SEC2TXT(SEC_I_SIGNATURE_NEEDED);
    971     default:
    972       txt = "Unknown error";
    973   }
    974 
    975   if(err == SEC_E_ILLEGAL_MESSAGE) {
    976     curl_msnprintf(buf, buflen,
    977                    "SEC_E_ILLEGAL_MESSAGE (0x%08X) - This error usually "
    978                    "occurs when a fatal SSL/TLS alert is received (e.g. "
    979                    "handshake failed). More detail may be available in "
    980                    "the Windows System event log.", err);
    981   }
    982   else {
    983     char msgbuf[256];
    984     if(curlx_get_winapi_error(err, msgbuf, sizeof(msgbuf)))
    985       curl_msnprintf(buf, buflen, "%s (0x%08X) - %s", txt, err, msgbuf);
    986     else
    987       curl_msnprintf(buf, buflen, "%s (0x%08X)", txt, err);
    988   }
    989 
    990 #else
    991   if(err == SEC_E_OK)
    992     txt = "No error";
    993   else
    994     txt = "Error";
    995   if(buflen > strlen(txt))
    996     strcpy(buf, txt);
    997 #endif
    998 
    999   if(errno != old_errno)
   1000     CURL_SETERRNO(old_errno);
   1001 
   1002 #ifdef _WIN32
   1003   if(old_win_err != GetLastError())
   1004     SetLastError(old_win_err);
   1005 #endif
   1006 
   1007   return buf;
   1008 }
   1009 #endif /* USE_WINDOWS_SSPI */