strerror.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 2004 - 2010, 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 http://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. * $Id$
  22. ***************************************************************************/
  23. #include "setup.h"
  24. #ifdef HAVE_STRERROR_R
  25. # if (!defined(HAVE_POSIX_STRERROR_R) && \
  26. !defined(HAVE_GLIBC_STRERROR_R) && \
  27. !defined(HAVE_VXWORKS_STRERROR_R)) || \
  28. (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \
  29. (defined(HAVE_GLIBC_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \
  30. (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R))
  31. # error "strerror_r MUST be either POSIX-style, glibc-style or vxworks-style"
  32. # endif
  33. #endif
  34. #include <curl/curl.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <errno.h>
  38. #ifdef USE_LIBIDN
  39. #include <idna.h>
  40. #endif
  41. #include "strerror.h"
  42. #define _MPRINTF_REPLACE /* use our functions only */
  43. #include <curl/mprintf.h>
  44. const char *
  45. curl_easy_strerror(CURLcode error)
  46. {
  47. #ifndef CURL_DISABLE_VERBOSE_STRINGS
  48. switch (error) {
  49. case CURLE_OK:
  50. return "No error";
  51. case CURLE_UNSUPPORTED_PROTOCOL:
  52. return "Unsupported protocol";
  53. case CURLE_FAILED_INIT:
  54. return "Failed initialization";
  55. case CURLE_URL_MALFORMAT:
  56. return "URL using bad/illegal format or missing URL";
  57. case CURLE_COULDNT_RESOLVE_PROXY:
  58. return "Couldn't resolve proxy name";
  59. case CURLE_COULDNT_RESOLVE_HOST:
  60. return "Couldn't resolve host name";
  61. case CURLE_COULDNT_CONNECT:
  62. return "Couldn't connect to server";
  63. case CURLE_FTP_WEIRD_SERVER_REPLY:
  64. return "FTP: weird server reply";
  65. case CURLE_REMOTE_ACCESS_DENIED:
  66. return "Access denied to remote resource";
  67. case CURLE_FTP_PRET_FAILED:
  68. return "FTP: The server did not accept the PRET command.";
  69. case CURLE_FTP_WEIRD_PASS_REPLY:
  70. return "FTP: unknown PASS reply";
  71. case CURLE_FTP_WEIRD_PASV_REPLY:
  72. return "FTP: unknown PASV reply";
  73. case CURLE_FTP_WEIRD_227_FORMAT:
  74. return "FTP: unknown 227 response format";
  75. case CURLE_FTP_CANT_GET_HOST:
  76. return "FTP: can't figure out the host in the PASV response";
  77. case CURLE_FTP_COULDNT_SET_TYPE:
  78. return "FTP: couldn't set file type";
  79. case CURLE_PARTIAL_FILE:
  80. return "Transferred a partial file";
  81. case CURLE_FTP_COULDNT_RETR_FILE:
  82. return "FTP: couldn't retrieve (RETR failed) the specified file";
  83. case CURLE_QUOTE_ERROR:
  84. return "Quote command returned error";
  85. case CURLE_HTTP_RETURNED_ERROR:
  86. return "HTTP response code said error";
  87. case CURLE_WRITE_ERROR:
  88. return "Failed writing received data to disk/application";
  89. case CURLE_UPLOAD_FAILED:
  90. return "Upload failed (at start/before it took off)";
  91. case CURLE_READ_ERROR:
  92. return "Failed to open/read local data from file/application";
  93. case CURLE_OUT_OF_MEMORY:
  94. return "Out of memory";
  95. case CURLE_OPERATION_TIMEDOUT:
  96. return "Timeout was reached";
  97. case CURLE_FTP_PORT_FAILED:
  98. return "FTP: command PORT failed";
  99. case CURLE_FTP_COULDNT_USE_REST:
  100. return "FTP: command REST failed";
  101. case CURLE_RANGE_ERROR:
  102. return "Requested range was not delivered by the server";
  103. case CURLE_HTTP_POST_ERROR:
  104. return "Internal problem setting up the POST";
  105. case CURLE_SSL_CONNECT_ERROR:
  106. return "SSL connect error";
  107. case CURLE_BAD_DOWNLOAD_RESUME:
  108. return "Couldn't resume download";
  109. case CURLE_FILE_COULDNT_READ_FILE:
  110. return "Couldn't read a file:// file";
  111. case CURLE_LDAP_CANNOT_BIND:
  112. return "LDAP: cannot bind";
  113. case CURLE_LDAP_SEARCH_FAILED:
  114. return "LDAP: search failed";
  115. case CURLE_FUNCTION_NOT_FOUND:
  116. return "A required function in the library was not found";
  117. case CURLE_ABORTED_BY_CALLBACK:
  118. return "Operation was aborted by an application callback";
  119. case CURLE_BAD_FUNCTION_ARGUMENT:
  120. return "A libcurl function was given a bad argument";
  121. case CURLE_INTERFACE_FAILED:
  122. return "Failed binding local connection end";
  123. case CURLE_TOO_MANY_REDIRECTS :
  124. return "Number of redirects hit maximum amount";
  125. case CURLE_UNKNOWN_TELNET_OPTION:
  126. return "User specified an unknown telnet option";
  127. case CURLE_TELNET_OPTION_SYNTAX :
  128. return "Malformed telnet option";
  129. case CURLE_PEER_FAILED_VERIFICATION:
  130. return "SSL peer certificate or SSH remote key was not OK";
  131. case CURLE_GOT_NOTHING:
  132. return "Server returned nothing (no headers, no data)";
  133. case CURLE_SSL_ENGINE_NOTFOUND:
  134. return "SSL crypto engine not found";
  135. case CURLE_SSL_ENGINE_SETFAILED:
  136. return "Can not set SSL crypto engine as default";
  137. case CURLE_SSL_ENGINE_INITFAILED:
  138. return "Failed to initialise SSL crypto engine";
  139. case CURLE_SEND_ERROR:
  140. return "Failed sending data to the peer";
  141. case CURLE_RECV_ERROR:
  142. return "Failure when receiving data from the peer";
  143. case CURLE_SSL_CERTPROBLEM:
  144. return "Problem with the local SSL certificate";
  145. case CURLE_SSL_CIPHER:
  146. return "Couldn't use specified SSL cipher";
  147. case CURLE_SSL_CACERT:
  148. return "Peer certificate cannot be authenticated with known CA certificates";
  149. case CURLE_SSL_CACERT_BADFILE:
  150. return "Problem with the SSL CA cert (path? access rights?)";
  151. case CURLE_BAD_CONTENT_ENCODING:
  152. return "Unrecognized HTTP Content-Encoding";
  153. case CURLE_LDAP_INVALID_URL:
  154. return "Invalid LDAP URL";
  155. case CURLE_FILESIZE_EXCEEDED:
  156. return "Maximum file size exceeded";
  157. case CURLE_USE_SSL_FAILED:
  158. return "Requested SSL level failed";
  159. case CURLE_SSL_SHUTDOWN_FAILED:
  160. return "Failed to shut down the SSL connection";
  161. case CURLE_SSL_CRL_BADFILE:
  162. return "Failed to load CRL file (path? access rights?, format?)";
  163. case CURLE_SSL_ISSUER_ERROR:
  164. return "Issuer check against peer certificate failed";
  165. case CURLE_SEND_FAIL_REWIND:
  166. return "Send failed since rewinding of the data stream failed";
  167. case CURLE_LOGIN_DENIED:
  168. return "Login denied";
  169. case CURLE_TFTP_NOTFOUND:
  170. return "TFTP: File Not Found";
  171. case CURLE_TFTP_PERM:
  172. return "TFTP: Access Violation";
  173. case CURLE_REMOTE_DISK_FULL:
  174. return "Disk full or allocation exceeded";
  175. case CURLE_TFTP_ILLEGAL:
  176. return "TFTP: Illegal operation";
  177. case CURLE_TFTP_UNKNOWNID:
  178. return "TFTP: Unknown transfer ID";
  179. case CURLE_REMOTE_FILE_EXISTS:
  180. return "Remote file already exists";
  181. case CURLE_TFTP_NOSUCHUSER:
  182. return "TFTP: No such user";
  183. case CURLE_CONV_FAILED:
  184. return "Conversion failed";
  185. case CURLE_CONV_REQD:
  186. return "Caller must register CURLOPT_CONV_ callback options";
  187. case CURLE_REMOTE_FILE_NOT_FOUND:
  188. return "Remote file not found";
  189. case CURLE_SSH:
  190. return "Error in the SSH layer";
  191. case CURLE_AGAIN:
  192. return "Socket not ready for send/recv";
  193. case CURLE_RTSP_CSEQ_ERROR:
  194. return "RTSP CSeq mismatch or invalid CSeq";
  195. case CURLE_RTSP_SESSION_ERROR:
  196. return "RTSP session error";
  197. /* error codes not used by current libcurl */
  198. case CURLE_OBSOLETE4:
  199. case CURLE_OBSOLETE10:
  200. case CURLE_OBSOLETE12:
  201. case CURLE_OBSOLETE16:
  202. case CURLE_OBSOLETE20:
  203. case CURLE_OBSOLETE24:
  204. case CURLE_OBSOLETE29:
  205. case CURLE_OBSOLETE32:
  206. case CURLE_OBSOLETE40:
  207. case CURLE_OBSOLETE44:
  208. case CURLE_OBSOLETE46:
  209. case CURLE_OBSOLETE50:
  210. case CURLE_OBSOLETE57:
  211. case CURL_LAST:
  212. break;
  213. }
  214. /*
  215. * By using a switch, gcc -Wall will complain about enum values
  216. * which do not appear, helping keep this function up-to-date.
  217. * By using gcc -Wall -Werror, you can't forget.
  218. *
  219. * A table would not have the same benefit. Most compilers will
  220. * generate code very similar to a table in any case, so there
  221. * is little performance gain from a table. And something is broken
  222. * for the user's application, anyways, so does it matter how fast
  223. * it _doesn't_ work?
  224. *
  225. * The line number for the error will be near this comment, which
  226. * is why it is here, and not at the start of the switch.
  227. */
  228. return "Unknown error";
  229. #else
  230. if(error == CURLE_OK)
  231. return "No error";
  232. else
  233. return "Error";
  234. #endif
  235. }
  236. const char *
  237. curl_multi_strerror(CURLMcode error)
  238. {
  239. #ifndef CURL_DISABLE_VERBOSE_STRINGS
  240. switch (error) {
  241. case CURLM_CALL_MULTI_PERFORM:
  242. return "Please call curl_multi_perform() soon";
  243. case CURLM_OK:
  244. return "No error";
  245. case CURLM_BAD_HANDLE:
  246. return "Invalid multi handle";
  247. case CURLM_BAD_EASY_HANDLE:
  248. return "Invalid easy handle";
  249. case CURLM_OUT_OF_MEMORY:
  250. return "Out of memory";
  251. case CURLM_INTERNAL_ERROR:
  252. return "Internal error";
  253. case CURLM_BAD_SOCKET:
  254. return "Invalid socket argument";
  255. case CURLM_UNKNOWN_OPTION:
  256. return "Unknown option";
  257. case CURLM_LAST:
  258. break;
  259. }
  260. return "Unknown error";
  261. #else
  262. if(error == CURLM_OK)
  263. return "No error";
  264. else
  265. return "Error";
  266. #endif
  267. }
  268. const char *
  269. curl_share_strerror(CURLSHcode error)
  270. {
  271. #ifndef CURL_DISABLE_VERBOSE_STRINGS
  272. switch (error) {
  273. case CURLSHE_OK:
  274. return "No error";
  275. case CURLSHE_BAD_OPTION:
  276. return "Unknown share option";
  277. case CURLSHE_IN_USE:
  278. return "Share currently in use";
  279. case CURLSHE_INVALID:
  280. return "Invalid share handle";
  281. case CURLSHE_NOMEM:
  282. return "Out of memory";
  283. case CURLSHE_LAST:
  284. break;
  285. }
  286. return "CURLSHcode unknown";
  287. #else
  288. if(error == CURLSHE_OK)
  289. return "No error";
  290. else
  291. return "Error";
  292. #endif
  293. }
  294. #ifdef USE_WINSOCK
  295. /* This function handles most / all (?) Winsock errors cURL is able to produce.
  296. */
  297. static const char *
  298. get_winsock_error (int err, char *buf, size_t len)
  299. {
  300. const char *p;
  301. #ifndef CURL_DISABLE_VERBOSE_STRINGS
  302. switch (err) {
  303. case WSAEINTR:
  304. p = "Call interrupted";
  305. break;
  306. case WSAEBADF:
  307. p = "Bad file";
  308. break;
  309. case WSAEACCES:
  310. p = "Bad access";
  311. break;
  312. case WSAEFAULT:
  313. p = "Bad argument";
  314. break;
  315. case WSAEINVAL:
  316. p = "Invalid arguments";
  317. break;
  318. case WSAEMFILE:
  319. p = "Out of file descriptors";
  320. break;
  321. case WSAEWOULDBLOCK:
  322. p = "Call would block";
  323. break;
  324. case WSAEINPROGRESS:
  325. case WSAEALREADY:
  326. p = "Blocking call in progress";
  327. break;
  328. case WSAENOTSOCK:
  329. p = "Descriptor is not a socket";
  330. break;
  331. case WSAEDESTADDRREQ:
  332. p = "Need destination address";
  333. break;
  334. case WSAEMSGSIZE:
  335. p = "Bad message size";
  336. break;
  337. case WSAEPROTOTYPE:
  338. p = "Bad protocol";
  339. break;
  340. case WSAENOPROTOOPT:
  341. p = "Protocol option is unsupported";
  342. break;
  343. case WSAEPROTONOSUPPORT:
  344. p = "Protocol is unsupported";
  345. break;
  346. case WSAESOCKTNOSUPPORT:
  347. p = "Socket is unsupported";
  348. break;
  349. case WSAEOPNOTSUPP:
  350. p = "Operation not supported";
  351. break;
  352. case WSAEAFNOSUPPORT:
  353. p = "Address family not supported";
  354. break;
  355. case WSAEPFNOSUPPORT:
  356. p = "Protocol family not supported";
  357. break;
  358. case WSAEADDRINUSE:
  359. p = "Address already in use";
  360. break;
  361. case WSAEADDRNOTAVAIL:
  362. p = "Address not available";
  363. break;
  364. case WSAENETDOWN:
  365. p = "Network down";
  366. break;
  367. case WSAENETUNREACH:
  368. p = "Network unreachable";
  369. break;
  370. case WSAENETRESET:
  371. p = "Network has been reset";
  372. break;
  373. case WSAECONNABORTED:
  374. p = "Connection was aborted";
  375. break;
  376. case WSAECONNRESET:
  377. p = "Connection was reset";
  378. break;
  379. case WSAENOBUFS:
  380. p = "No buffer space";
  381. break;
  382. case WSAEISCONN:
  383. p = "Socket is already connected";
  384. break;
  385. case WSAENOTCONN:
  386. p = "Socket is not connected";
  387. break;
  388. case WSAESHUTDOWN:
  389. p = "Socket has been shut down";
  390. break;
  391. case WSAETOOMANYREFS:
  392. p = "Too many references";
  393. break;
  394. case WSAETIMEDOUT:
  395. p = "Timed out";
  396. break;
  397. case WSAECONNREFUSED:
  398. p = "Connection refused";
  399. break;
  400. case WSAELOOP:
  401. p = "Loop??";
  402. break;
  403. case WSAENAMETOOLONG:
  404. p = "Name too long";
  405. break;
  406. case WSAEHOSTDOWN:
  407. p = "Host down";
  408. break;
  409. case WSAEHOSTUNREACH:
  410. p = "Host unreachable";
  411. break;
  412. case WSAENOTEMPTY:
  413. p = "Not empty";
  414. break;
  415. case WSAEPROCLIM:
  416. p = "Process limit reached";
  417. break;
  418. case WSAEUSERS:
  419. p = "Too many users";
  420. break;
  421. case WSAEDQUOT:
  422. p = "Bad quota";
  423. break;
  424. case WSAESTALE:
  425. p = "Something is stale";
  426. break;
  427. case WSAEREMOTE:
  428. p = "Remote error";
  429. break;
  430. #ifdef WSAEDISCON /* missing in SalfordC! */
  431. case WSAEDISCON:
  432. p = "Disconnected";
  433. break;
  434. #endif
  435. /* Extended Winsock errors */
  436. case WSASYSNOTREADY:
  437. p = "Winsock library is not ready";
  438. break;
  439. case WSANOTINITIALISED:
  440. p = "Winsock library not initialised";
  441. break;
  442. case WSAVERNOTSUPPORTED:
  443. p = "Winsock version not supported";
  444. break;
  445. /* getXbyY() errors (already handled in herrmsg):
  446. * Authoritative Answer: Host not found */
  447. case WSAHOST_NOT_FOUND:
  448. p = "Host not found";
  449. break;
  450. /* Non-Authoritative: Host not found, or SERVERFAIL */
  451. case WSATRY_AGAIN:
  452. p = "Host not found, try again";
  453. break;
  454. /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
  455. case WSANO_RECOVERY:
  456. p = "Unrecoverable error in call to nameserver";
  457. break;
  458. /* Valid name, no data record of requested type */
  459. case WSANO_DATA:
  460. p = "No data record of requested type";
  461. break;
  462. default:
  463. return NULL;
  464. }
  465. #else
  466. if(err == CURLE_OK)
  467. return NULL;
  468. else
  469. p = "error";
  470. #endif
  471. strncpy (buf, p, len);
  472. buf [len-1] = '\0';
  473. return buf;
  474. }
  475. #endif /* USE_WINSOCK */
  476. /*
  477. * Our thread-safe and smart strerror() replacement.
  478. *
  479. * The 'err' argument passed in to this function MUST be a true errno number
  480. * as reported on this system. We do no range checking on the number before
  481. * we pass it to the "number-to-message" conversion function and there might
  482. * be systems that don't do proper range checking in there themselves.
  483. *
  484. * We don't do range checking (on systems other than Windows) since there is
  485. * no good reliable and portable way to do it.
  486. */
  487. const char *Curl_strerror(struct connectdata *conn, int err)
  488. {
  489. char *buf, *p;
  490. size_t max;
  491. int old_errno = ERRNO;
  492. DEBUGASSERT(conn);
  493. DEBUGASSERT(err >= 0);
  494. buf = conn->syserr_buf;
  495. max = sizeof(conn->syserr_buf)-1;
  496. *buf = '\0';
  497. #ifdef USE_WINSOCK
  498. #ifdef _WIN32_WCE
  499. {
  500. wchar_t wbuf[256];
  501. wbuf[0] = L'\0';
  502. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
  503. LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL);
  504. wcstombs(buf,wbuf,max);
  505. }
  506. #else
  507. /* 'sys_nerr' is the maximum errno number, it is not widely portable */
  508. if(err >= 0 && err < sys_nerr)
  509. strncpy(buf, strerror(err), max);
  510. else {
  511. if(!get_winsock_error(err, buf, max) &&
  512. !FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
  513. LANG_NEUTRAL, buf, (DWORD)max, NULL))
  514. snprintf(buf, max, "Unknown error %d (%#x)", err, err);
  515. }
  516. #endif
  517. #else /* not USE_WINSOCK coming up */
  518. #if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R)
  519. /*
  520. * The POSIX-style strerror_r() may set errno to ERANGE if insufficient
  521. * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated
  522. * message string, or EINVAL if 'errnum' is not a valid error number.
  523. */
  524. if(0 != strerror_r(err, buf, max)) {
  525. if('\0' == buf[0])
  526. snprintf(buf, max, "Unknown error %d", err);
  527. }
  528. #elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
  529. /*
  530. * The glibc-style strerror_r() only *might* use the buffer we pass to
  531. * the function, but it always returns the error message as a pointer,
  532. * so we must copy that string unconditionally (if non-NULL).
  533. */
  534. {
  535. char buffer[256];
  536. char *msg = strerror_r(err, buffer, sizeof(buffer));
  537. if(msg)
  538. strncpy(buf, msg, max);
  539. else
  540. snprintf(buf, max, "Unknown error %d", err);
  541. }
  542. #elif defined(HAVE_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)
  543. /*
  544. * The vxworks-style strerror_r() does use the buffer we pass to the function.
  545. * The buffer size should be at least MAXERRSTR_SIZE (150) defined in rtsold.h
  546. */
  547. {
  548. char buffer[256];
  549. if(OK == strerror_r(err, buffer))
  550. strncpy(buf, buffer, max);
  551. else
  552. snprintf(buf, max, "Unknown error %d", err);
  553. }
  554. #else
  555. {
  556. char *msg = strerror(err);
  557. if(msg)
  558. strncpy(buf, msg, max);
  559. else
  560. snprintf(buf, max, "Unknown error %d", err);
  561. }
  562. #endif
  563. #endif /* end of ! USE_WINSOCK */
  564. buf[max] = '\0'; /* make sure the string is zero terminated */
  565. /* strip trailing '\r\n' or '\n'. */
  566. if((p = strrchr(buf,'\n')) != NULL && (p - buf) >= 2)
  567. *p = '\0';
  568. if((p = strrchr(buf,'\r')) != NULL && (p - buf) >= 1)
  569. *p = '\0';
  570. if(old_errno != ERRNO)
  571. SET_ERRNO(old_errno);
  572. return buf;
  573. }
  574. #ifdef USE_LIBIDN
  575. /*
  576. * Return error-string for libidn status as returned from idna_to_ascii_lz().
  577. */
  578. const char *Curl_idn_strerror (struct connectdata *conn, int err)
  579. {
  580. #ifdef HAVE_IDNA_STRERROR
  581. (void)conn;
  582. return idna_strerror((Idna_rc) err);
  583. #else
  584. const char *str;
  585. char *buf;
  586. size_t max;
  587. DEBUGASSERT(conn);
  588. buf = conn->syserr_buf;
  589. max = sizeof(conn->syserr_buf)-1;
  590. *buf = '\0';
  591. #ifndef CURL_DISABLE_VERBOSE_STRINGS
  592. switch ((Idna_rc)err) {
  593. case IDNA_SUCCESS:
  594. str = "No error";
  595. break;
  596. case IDNA_STRINGPREP_ERROR:
  597. str = "Error in string preparation";
  598. break;
  599. case IDNA_PUNYCODE_ERROR:
  600. str = "Error in Punycode operation";
  601. break;
  602. case IDNA_CONTAINS_NON_LDH:
  603. str = "Illegal ASCII characters";
  604. break;
  605. case IDNA_CONTAINS_MINUS:
  606. str = "Contains minus";
  607. break;
  608. case IDNA_INVALID_LENGTH:
  609. str = "Invalid output length";
  610. break;
  611. case IDNA_NO_ACE_PREFIX:
  612. str = "No ACE prefix (\"xn--\")";
  613. break;
  614. case IDNA_ROUNDTRIP_VERIFY_ERROR:
  615. str = "Round trip verify error";
  616. break;
  617. case IDNA_CONTAINS_ACE_PREFIX:
  618. str = "Already have ACE prefix (\"xn--\")";
  619. break;
  620. case IDNA_ICONV_ERROR:
  621. str = "Locale conversion failed";
  622. break;
  623. case IDNA_MALLOC_ERROR:
  624. str = "Allocation failed";
  625. break;
  626. case IDNA_DLOPEN_ERROR:
  627. str = "dlopen() error";
  628. break;
  629. default:
  630. snprintf(buf, max, "error %d", err);
  631. str = NULL;
  632. break;
  633. }
  634. #else
  635. if((Idna_rc)err == IDNA_SUCCESS)
  636. str = "No error";
  637. else
  638. str = "Error";
  639. #endif
  640. if(str)
  641. strncpy(buf, str, max);
  642. buf[max] = '\0';
  643. return (buf);
  644. #endif
  645. }
  646. #endif /* USE_LIBIDN */