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