Coverage Report

Created: 2025-06-09 07:07

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