File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / strerror.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (5 years, 6 months ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>