Annotation of embedaddon/curl/lib/strerror.c, revision 1.1
1.1 ! misho 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>