]> sjero.net Git - wget/blob - src/mswindows.c
[svn] Correctly print SSL errors.
[wget] / src / mswindows.c
1 /* mswindows.c -- Windows-specific support
2    Copyright (C) 1996-2005 Free Software Foundation, Inc.
3
4 This file is part of GNU Wget.
5
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
20 In addition, as a special exception, the Free Software Foundation
21 gives permission to link the code of its release of Wget with the
22 OpenSSL project's "OpenSSL" library (or with modified versions of it
23 that use the same license as the "OpenSSL" library), and distribute
24 the linked executables.  You must obey the GNU General Public License
25 in all respects for all of the code used other than "OpenSSL".  If you
26 modify this file, you may extend this exception to your version of the
27 file, but you are not obligated to do so.  If you do not wish to do
28 so, delete this exception statement from your version.  */
29
30 #include <config.h>
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <assert.h>
36 #include <errno.h>
37 #include <math.h>
38
39 #ifdef HACK_BCC_UTIME_BUG
40 # include <io.h>
41 # include <fcntl.h>
42 # ifdef HAVE_UTIME_H
43 #  include <utime.h>
44 # endif
45 # ifdef HAVE_SYS_UTIME_H
46 #  include <sys/utime.h>
47 # endif
48 #endif
49
50 #define INHIBIT_WRAP /* avoid wrapping of socket, bind, ... */
51
52 #include "wget.h"
53 #include "utils.h"
54 #include "url.h"
55
56 #ifndef ES_SYSTEM_REQUIRED
57 #define ES_SYSTEM_REQUIRED  0x00000001
58 #endif
59
60 #ifndef ES_CONTINUOUS
61 #define ES_CONTINUOUS       0x80000000
62 #endif
63
64
65 /* Defined in log.c.  */
66 void log_request_redirect_output (const char *);
67
68 /* Windows version of xsleep in utils.c.  */
69
70 void
71 xsleep (double seconds)
72 {
73 #ifdef HAVE_USLEEP
74   if (seconds > 1000)
75     {
76       /* Explained in utils.c. */
77       sleep (seconds);
78       seconds -= (long) seconds;
79     }
80   usleep (seconds * 1000000L);
81 #else  /* not HAVE_USLEEP */
82   SleepEx ((DWORD) (seconds * 1000 + .5), FALSE);
83 #endif /* not HAVE_USLEEP */
84 }
85
86 #if defined(__BORLANDC__) || (defined(_MSC_VER) && _MSC_VER < 1300)
87
88 static inline int
89 char_value (char c, int base)
90 {
91   int value;
92   if (c < '0')
93     return -1;
94   if ('0' <= c && c <= '9')
95     value = c - '0';
96   else if ('a' <= c && c <= 'z')
97     value = c - 'a' + 10;
98   else if ('A' <= c && c <= 'Z')
99     value = c - 'A' + 10;
100   else
101     return -1;
102   if (value >= base)
103     return -1;
104   return value;
105 }
106
107 /* A fairly simple strtoll replacement for MS VC versions that don't
108    supply _strtoi64.  */
109
110 __int64
111 str_to_int64 (const char *nptr, char **endptr, int base)
112 {
113 #define INT64_OVERFLOW 9223372036854775807I64
114 #define INT64_UNDERFLOW (-INT64_OVERFLOW - 1)
115
116   __int64 result = 0;
117   bool negative;
118
119   if (base != 0 && (base < 2 || base > 36))
120     {
121       errno = EINVAL;
122       return 0;
123     }
124
125   while (*nptr == ' ' || *nptr == '\t')
126     ++nptr;
127   if (*nptr == '-')
128     {
129       negative = true;
130       ++nptr;
131     }
132   else if (*nptr == '+')
133     {
134       negative = false;
135       ++nptr;
136     }
137   else
138     negative = false;
139
140   /* If base is 0, determine the real base based on the beginning on
141      the number; octal numbers begin with "0", hexadecimal with "0x",
142      and the others are considered octal.  */
143   if (*nptr == '0')
144     {
145       if ((base == 0 || base == 16)
146           &&
147           (*(nptr + 1) == 'x' || *(nptr + 1) == 'X'))
148         {
149           base = 16;
150           nptr += 2;
151         }
152       else if (base == 0)
153         base = 8;
154     }
155   else if (base == 0)
156     base = 10;
157
158   if (!negative)
159     {
160       /* Parse positive number, checking for overflow. */
161       int val;
162       for (; (val = char_value (*nptr, base)) != -1; ++nptr)
163         {
164           __int64 newresult = base * result + val;
165           if (newresult < result)
166             {
167               result = INT64_OVERFLOW;
168               errno = ERANGE;
169               break;
170             }
171           result = newresult;
172         }
173     }
174   else
175     {
176       /* Parse negative number, checking for underflow. */
177       int val;
178       for (; (val = char_value (*nptr, base)) != -1; ++nptr)
179         {
180           __int64 newresult = base * result - val;
181           if (newresult > result)
182             {
183               result = INT64_UNDERFLOW;
184               errno = ERANGE;
185               break;
186             }
187           result = newresult;
188         }
189     }
190   if (endptr)
191     *endptr = (char *) nptr;
192   return result;
193 }
194
195 #else  /* !defined(__BORLANDC__) && (!defined(_MSC_VER) || _MSC_VER >= 1300) */
196
197 __int64
198 str_to_int64 (const char *nptr, char **endptr, int base)
199 {
200 #ifdef _MSC_VER
201   return _strtoi64 (nptr, endptr, base);
202 #else
203   return strtoll (nptr, endptr, base);
204 #endif
205 }
206
207 #endif /* !defined(__BORLANDC__) && (!defined(_MSC_VER) || _MSC_VER >= 1300) */
208
209 void
210 windows_main (int *argc, char **argv, char **exec_name)
211 {
212   char *p;
213
214   /* Remove .EXE from filename if it has one.  */
215   *exec_name = xstrdup (*exec_name);
216   p = strrchr (*exec_name, '.');
217   if (p)
218     *p = '\0';
219 }
220 \f
221 static void
222 ws_cleanup (void)
223 {
224   WSACleanup ();
225 }
226
227 static void
228 ws_hangup (const char *reason)
229 {
230   fprintf (stderr, _("Continuing in background.\n"));
231   log_request_redirect_output (reason);
232
233   /* Detach process from the current console.  Under Windows 9x, if we
234      were launched from a 16-bit process (which is usually the case;
235      command.com is 16-bit) the parent process should resume right away.
236      Under NT or if launched from a 32-process under 9x, this is a futile
237      gesture as the parent will wait for us to terminate before resuming.  */
238   FreeConsole ();
239 }
240
241 /* Construct the name for a named section (a.k.a. `file mapping') object.
242    The returned string is dynamically allocated and needs to be xfree()'d.  */
243 static char *
244 make_section_name (DWORD pid)
245 {
246   return aprintf ("gnu_wget_fake_fork_%lu", pid);
247 }
248
249 /* This structure is used to hold all the data that is exchanged between
250    parent and child.  */
251 struct fake_fork_info
252 {
253   HANDLE event;
254   bool logfile_changed;
255   char lfilename[MAX_PATH + 1];
256 };
257
258 /* Determines if we are the child and if so performs the child logic.
259    Return values:
260      < 0  error
261        0  parent
262      > 0  child
263 */
264 static int
265 fake_fork_child (void)
266 {
267   HANDLE section, event;
268   struct fake_fork_info *info;
269   char *name;
270
271   name = make_section_name (GetCurrentProcessId ());
272   section = OpenFileMapping (FILE_MAP_WRITE, FALSE, name);
273   xfree (name);
274   /* It seems that Windows 9x and NT set last-error inconsistently when
275      OpenFileMapping() fails; so we assume it failed because the section
276      object does not exist.  */
277   if (!section)
278     return 0;                   /* We are the parent.  */
279
280   info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
281   if (!info)
282     {
283       CloseHandle (section);
284       return -1;
285     }
286
287   event = info->event;
288
289   info->logfile_changed = false;
290   if (!opt.lfilename)
291     {
292       /* See utils:fork_to_background for explanation. */
293       FILE *new_log_fp = unique_create (DEFAULT_LOGFILE, false, &opt.lfilename);
294       if (new_log_fp)
295         {
296           info->logfile_changed = true;
297           strncpy (info->lfilename, opt.lfilename, sizeof (info->lfilename));
298           info->lfilename[sizeof (info->lfilename) - 1] = '\0';
299           fclose (new_log_fp);
300         }
301     }
302
303   UnmapViewOfFile (info);
304   CloseHandle (section);
305
306   /* Inform the parent that we've done our part.  */
307   if (!SetEvent (event))
308     return -1;
309
310   CloseHandle (event);
311   return 1;                     /* We are the child.  */
312 }
313
314 /* Windows doesn't support the fork() call; so we fake it by invoking
315    another copy of Wget with the same arguments with which we were
316    invoked.  The child copy of Wget should perform the same initialization
317    sequence as the parent; so we should have two processes that are
318    essentially identical.  We create a specially named section object that
319    allows the child to distinguish itself from the parent and is used to
320    exchange information between the two processes.  We use an event object
321    for synchronization.  */
322 static void
323 fake_fork (void)
324 {
325   char exe[MAX_PATH + 1];
326   DWORD exe_len, le;
327   SECURITY_ATTRIBUTES sa;
328   HANDLE section, event, h[2];
329   STARTUPINFO si;
330   PROCESS_INFORMATION pi;
331   struct fake_fork_info *info;
332   char *name;
333   BOOL rv;
334
335   section = pi.hProcess = pi.hThread = NULL;
336
337   /* Get the fully qualified name of our executable.  This is more reliable
338      than using argv[0].  */
339   exe_len = GetModuleFileName (GetModuleHandle (NULL), exe, sizeof (exe));
340   if (!exe_len || (exe_len >= sizeof (exe)))
341     return;
342
343   sa.nLength = sizeof (sa);
344   sa.lpSecurityDescriptor = NULL;
345   sa.bInheritHandle = TRUE;
346
347   /* Create an anonymous inheritable event object that starts out
348      non-signaled.  */
349   event = CreateEvent (&sa, FALSE, FALSE, NULL);
350   if (!event)
351     return;
352
353   /* Create the child process detached form the current console and in a
354      suspended state.  */
355   xzero (si);
356   si.cb = sizeof (si);
357   rv = CreateProcess (exe, GetCommandLine (), NULL, NULL, TRUE,
358                       CREATE_SUSPENDED | DETACHED_PROCESS,
359                       NULL, NULL, &si, &pi);
360   if (!rv)
361     goto cleanup;
362
363   /* Create a named section object with a name based on the process id of
364      the child.  */
365   name = make_section_name (pi.dwProcessId);
366   section =
367       CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
368                          sizeof (struct fake_fork_info), name);
369   le = GetLastError();
370   xfree (name);
371   /* Fail if the section object already exists (should not happen).  */
372   if (!section || (le == ERROR_ALREADY_EXISTS))
373     {
374       rv = FALSE;
375       goto cleanup;
376     }
377
378   /* Copy the event handle into the section object.  */
379   info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
380   if (!info)
381     {
382       rv = FALSE;
383       goto cleanup;
384     }
385
386   info->event = event;
387
388   UnmapViewOfFile (info);
389
390   /* Start the child process.  */
391   rv = ResumeThread (pi.hThread);
392   if (!rv)
393     {
394       TerminateProcess (pi.hProcess, (DWORD) -1);
395       goto cleanup;
396     }
397
398   /* Wait for the child to signal to us that it has done its part.  If it
399      terminates before signaling us it's an error.  */
400
401   h[0] = event;
402   h[1] = pi.hProcess;
403   rv = WAIT_OBJECT_0 == WaitForMultipleObjects (2, h, FALSE, 5 * 60 * 1000);
404   if (!rv)
405     goto cleanup;
406
407   info = MapViewOfFile (section, FILE_MAP_READ, 0, 0, 0);
408   if (!info)
409     {
410       rv = FALSE;
411       goto cleanup;
412     }
413
414   /* Ensure string is properly terminated.  */
415   if (info->logfile_changed &&
416       !memchr (info->lfilename, '\0', sizeof (info->lfilename)))
417     {
418       rv = FALSE;
419       goto cleanup;
420     }
421
422   printf (_("Continuing in background, pid %lu.\n"), pi.dwProcessId);
423   if (info->logfile_changed)
424     printf (_("Output will be written to `%s'.\n"), info->lfilename);
425
426   UnmapViewOfFile (info);
427
428 cleanup:
429
430   if (event)
431     CloseHandle (event);
432   if (section)
433     CloseHandle (section);
434   if (pi.hThread)
435     CloseHandle (pi.hThread);
436   if (pi.hProcess)
437     CloseHandle (pi.hProcess);
438
439   /* We're the parent.  If all is well, terminate.  */
440   if (rv)
441     exit (0);
442
443   /* We failed, return.  */
444 }
445
446 /* This is the corresponding Windows implementation of the
447    fork_to_background() function in utils.c.  */
448 void
449 fork_to_background (void)
450 {
451   int rv;
452
453   rv = fake_fork_child ();
454   if (rv < 0)
455     {
456       fprintf (stderr, "fake_fork_child() failed\n");
457       abort ();
458     }
459   else if (rv == 0)
460     {
461       /* We're the parent.  */
462       fake_fork ();
463       /* If fake_fork() returns, it failed.  */
464       fprintf (stderr, "fake_fork() failed\n");
465       abort ();
466     }
467   /* If we get here, we're the child.  */
468 }
469
470 static BOOL WINAPI
471 ws_handler (DWORD dwEvent)
472 {
473   switch (dwEvent)
474     {
475 #ifdef CTRLC_BACKGND
476     case CTRL_C_EVENT:
477       ws_hangup ("CTRL+C");
478       return TRUE;
479 #endif
480 #ifdef CTRLBREAK_BACKGND
481     case CTRL_BREAK_EVENT:
482       ws_hangup ("CTRL+Break");
483       return TRUE;
484 #endif
485     default:
486       return FALSE;
487     }
488 }
489
490 static char *title_buf = NULL;
491 static char *curr_url  = NULL;
492 static int old_percentage = -1;
493
494 /* Updates the console title with the URL of the current file being
495    transferred.  */
496 void
497 ws_changetitle (const char *url)
498 {
499   xfree_null (title_buf);
500   xfree_null (curr_url);
501   title_buf = xmalloc (strlen (url) + 20);
502   curr_url = xstrdup (url);
503   old_percentage = -1;
504   sprintf (title_buf, "Wget %s", curr_url);
505   SetConsoleTitle (title_buf);
506 }
507
508 /* Updates the console title with the percentage of the current file
509    transferred.  */
510 void
511 ws_percenttitle (double percentage_float)
512 {
513   int percentage;
514
515   if (!title_buf || !curr_url)
516     return;
517
518   percentage = (int) percentage_float;
519
520   /* Clamp percentage value.  */
521   if (percentage < 0)
522     percentage = 0;
523   if (percentage > 100)
524     percentage = 100;
525
526   /* Only update the title when the percentage has changed.  */
527   if (percentage == old_percentage)
528     return;
529
530   old_percentage = percentage;
531
532   sprintf (title_buf, "Wget [%d%%] %s", percentage, curr_url);
533   SetConsoleTitle (title_buf);
534 }
535
536 /* Returns a pointer to the fully qualified name of the directory that
537    contains the Wget binary (wget.exe).  The returned path does not have a
538    trailing path separator.  Returns NULL on failure.  */
539 char *
540 ws_mypath (void)
541 {
542   static char *wspathsave = NULL;
543
544   if (!wspathsave)
545     {
546       char buf[MAX_PATH + 1];
547       char *p;
548       DWORD len;
549
550       len = GetModuleFileName (GetModuleHandle (NULL), buf, sizeof (buf));
551       if (!len || (len >= sizeof (buf)))
552         return NULL;
553
554       p = strrchr (buf, PATH_SEPARATOR);
555       if (!p)
556         return NULL;
557
558       *p = '\0';
559       wspathsave = xstrdup (buf);
560     }
561
562   return wspathsave;
563 }
564
565 /* Prevent Windows entering sleep/hibernation-mode while Wget is doing
566    a lengthy transfer.  Windows does not, by default, consider network
567    activity in console-programs as activity!  Works on Win-98/ME/2K
568    and up.  */
569 static void
570 set_sleep_mode (void)
571 {
572   typedef DWORD (WINAPI *func_t) (DWORD);
573   func_t set_exec_state;
574
575   set_exec_state =
576       (func_t) GetProcAddress (GetModuleHandle ("KERNEL32.DLL"),
577                                "SetThreadExecutionState");
578
579   if (set_exec_state)
580     set_exec_state (ES_SYSTEM_REQUIRED | ES_CONTINUOUS);
581 }
582
583 /* Perform Windows specific initialization.  */
584 void
585 ws_startup (void)
586 {
587   WSADATA data;
588   WORD requested = MAKEWORD (1, 1);
589   int err = WSAStartup (requested, &data);
590   if (err != 0)
591     {
592       fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
593                exec_name);
594       exit (1);
595     }
596
597   if (data.wVersion < requested)
598     {
599       fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
600                exec_name);
601       WSACleanup ();
602       exit (1);
603     }
604
605   atexit (ws_cleanup);
606   set_sleep_mode ();
607   SetConsoleCtrlHandler (ws_handler, TRUE);
608 }
609
610 /* Replacement utime function for buggy Borland C++Builder 5.5 compiler.
611    (The Borland utime function only works on Windows NT.)  */
612
613 #ifdef HACK_BCC_UTIME_BUG
614 int
615 borland_utime (const char *path, const struct utimbuf *times)
616 {
617   int fd;
618   int res;
619   struct ftime ft;
620   struct tm *ptr_tm;
621
622   if ((fd = open (path, O_RDWR)) < 0)
623     return -1;
624
625   ptr_tm = localtime (&times->modtime);
626   ft.ft_tsec = ptr_tm->tm_sec >> 1;
627   ft.ft_min = ptr_tm->tm_min;
628   ft.ft_hour = ptr_tm->tm_hour;
629   ft.ft_day = ptr_tm->tm_mday;
630   ft.ft_month = ptr_tm->tm_mon + 1;
631   ft.ft_year = ptr_tm->tm_year - 80;
632   res = setftime (fd, &ft);
633   close (fd);
634   return res;
635 }
636 #endif
637 \f
638 /* run_with_timeout Windows implementation.  */
639
640 /* Stack size 0 uses default thread stack-size (reserve+commit).
641    Determined by what's in the PE header.  */
642 #define THREAD_STACK_SIZE  0
643
644 struct thread_data
645 {
646   void (*fun) (void *);
647   void *arg;
648   DWORD ws_error;
649 };
650
651 /* The callback that runs FUN(ARG) in a separate thread.  This
652    function exists for two reasons: a) to not require FUN to be
653    declared WINAPI/__stdcall[1], and b) to retrieve Winsock errors,
654    which are per-thread.  The latter is useful when FUN calls Winsock
655    functions, which is how run_with_timeout is used in Wget.
656
657    [1] MSVC can use __fastcall globally (cl /Gr) and on Watcom this is
658    the default (wcc386 -3r).  */
659
660 static DWORD WINAPI
661 thread_helper (void *arg)
662 {
663   struct thread_data *td = (struct thread_data *) arg;
664
665   /* Initialize Winsock error to what it was in the parent.  That way
666      the subsequent call to WSAGetLastError will return the same value
667      if td->fun doesn't change Winsock error state.  */
668   WSASetLastError (td->ws_error);
669
670   td->fun (td->arg);
671
672   /* Return Winsock error to the caller, in case FUN ran Winsock
673      code.  */
674   td->ws_error = WSAGetLastError ();
675   return 0;
676 }
677
678 /* Call FUN(ARG), but don't allow it to run for more than TIMEOUT
679    seconds.  Returns true if the function was interrupted with a
680    timeout, false otherwise.
681
682    This works by running FUN in a separate thread and terminating the
683    thread if it doesn't finish in the specified time.  */
684
685 bool
686 run_with_timeout (double seconds, void (*fun) (void *), void *arg)
687 {
688   static HANDLE thread_hnd = NULL;
689   struct thread_data thread_arg;
690   DWORD thread_id;
691   bool rc;
692
693   DEBUGP (("seconds %.2f, ", seconds));
694
695   if (seconds == 0)
696     {
697     blocking_fallback:
698       fun (arg);
699       return false;
700     }
701
702   /* Should never happen, but test for recursivety anyway.  */
703   assert (thread_hnd == NULL);
704
705   thread_arg.fun = fun;
706   thread_arg.arg = arg;
707   thread_arg.ws_error = WSAGetLastError ();
708   thread_hnd = CreateThread (NULL, THREAD_STACK_SIZE, thread_helper,
709                              &thread_arg, 0, &thread_id);
710   if (!thread_hnd)
711     {
712       DEBUGP (("CreateThread() failed; [0x%x]\n", GetLastError ()));
713       goto blocking_fallback;
714     }
715
716   if (WaitForSingleObject (thread_hnd, (DWORD)(1000 * seconds))
717       == WAIT_OBJECT_0)
718     {
719       /* Propagate error state (which is per-thread) to this thread,
720          so the caller can inspect it.  */
721       WSASetLastError (thread_arg.ws_error);
722       DEBUGP (("Winsock error: %d\n", WSAGetLastError ()));
723       rc = false;
724     }
725   else
726     {
727       TerminateThread (thread_hnd, 1);
728       rc = true;
729     }
730
731   CloseHandle (thread_hnd);     /* Clear-up after TerminateThread().  */
732   thread_hnd = NULL;
733   return rc;
734 }
735 \f
736 /* Wget expects network calls such as connect, recv, send, etc., to set
737    errno on failure.  To achieve that, Winsock calls are wrapped with code
738    that, in case of error, sets errno to the value of WSAGetLastError().
739    In addition, we provide a wrapper around strerror, which recognizes
740    Winsock errors and prints the appropriate error message. */
741
742 /* Define a macro that creates a function definition that wraps FUN into
743    a function that sets errno the way the rest of the code expects. */
744
745 #define WRAP(fun, decl, call) int wrapped_##fun decl {  \
746   int retval = fun call;                                \
747   if (retval < 0)                                       \
748     errno = WSAGetLastError ();                         \
749   return retval;                                        \
750 }
751
752 WRAP (socket, (int domain, int type, int protocol), (domain, type, protocol))
753 WRAP (bind, (int s, struct sockaddr *a, int alen), (s, a, alen))
754 WRAP (connect, (int s, const struct sockaddr *a, int alen), (s, a, alen))
755 WRAP (listen, (int s, int backlog), (s, backlog))
756 WRAP (accept, (int s, struct sockaddr *a, int *alen), (s, a, alen))
757 WRAP (recv, (int s, void *buf, int len, int flags), (s, buf, len, flags))
758 WRAP (send, (int s, const void *buf, int len, int flags), (s, buf, len, flags))
759 WRAP (select, (int n, fd_set *r, fd_set *w, fd_set *e, const struct timeval *tm),
760               (n, r, w, e, tm))
761 WRAP (getsockname, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
762 WRAP (getpeername, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
763 WRAP (setsockopt, (int s, int level, int opt, const void *val, int len),
764                   (s, level, opt, val, len))
765 WRAP (closesocket, (int s), (s))
766
767 /* Return the text of the error message for Winsock error WSERR. */
768
769 static const char *
770 get_winsock_error (int wserr)
771 {
772   switch (wserr) {
773   case WSAEINTR:           return "Interrupted system call";
774   case WSAEBADF:           return "Bad file number";
775   case WSAEACCES:          return "Permission denied";
776   case WSAEFAULT:          return "Bad address";
777   case WSAEINVAL:          return "Invalid argument";
778   case WSAEMFILE:          return "Too many open files";
779   case WSAEWOULDBLOCK:     return "Resource temporarily unavailable";
780   case WSAEINPROGRESS:     return "Operation now in progress";
781   case WSAEALREADY:        return "Operation already in progress";
782   case WSAENOTSOCK:        return "Socket operation on nonsocket";
783   case WSAEDESTADDRREQ:    return "Destination address required";
784   case WSAEMSGSIZE:        return "Message too long";
785   case WSAEPROTOTYPE:      return "Protocol wrong type for socket";
786   case WSAENOPROTOOPT:     return "Bad protocol option";
787   case WSAEPROTONOSUPPORT: return "Protocol not supported";
788   case WSAESOCKTNOSUPPORT: return "Socket type not supported";
789   case WSAEOPNOTSUPP:      return "Operation not supported";
790   case WSAEPFNOSUPPORT:    return "Protocol family not supported";
791   case WSAEAFNOSUPPORT:    return "Address family not supported by protocol family";
792   case WSAEADDRINUSE:      return "Address already in use";
793   case WSAEADDRNOTAVAIL:   return "Cannot assign requested address";
794   case WSAENETDOWN:        return "Network is down";
795   case WSAENETUNREACH:     return "Network is unreachable";
796   case WSAENETRESET:       return "Network dropped connection on reset";
797   case WSAECONNABORTED:    return "Software caused connection abort";
798   case WSAECONNRESET:      return "Connection reset by peer";
799   case WSAENOBUFS:         return "No buffer space available";
800   case WSAEISCONN:         return "Socket is already connected";
801   case WSAENOTCONN:        return "Socket is not connected";
802   case WSAESHUTDOWN:       return "Cannot send after socket shutdown";
803   case WSAETOOMANYREFS:    return "Too many references";
804   case WSAETIMEDOUT:       return "Connection timed out";
805   case WSAECONNREFUSED:    return "Connection refused";
806   case WSAELOOP:           return "Too many levels of symbolic links";
807   case WSAENAMETOOLONG:    return "File name too long";
808   case WSAEHOSTDOWN:       return "Host is down";
809   case WSAEHOSTUNREACH:    return "No route to host";
810   case WSAENOTEMPTY:       return "Not empty";
811   case WSAEPROCLIM:        return "Too many processes";
812   case WSAEUSERS:          return "Too many users";
813   case WSAEDQUOT:          return "Bad quota";
814   case WSAESTALE:          return "Something is stale";
815   case WSAEREMOTE:         return "Remote error";
816   case WSAEDISCON:         return "Disconnected";
817
818   /* Extended Winsock errors */
819   case WSASYSNOTREADY:     return "Winsock library is not ready";
820   case WSANOTINITIALISED:  return "Winsock library not initalised";
821   case WSAVERNOTSUPPORTED: return "Winsock version not supported";
822
823   case WSAHOST_NOT_FOUND: return "Host not found";
824   case WSATRY_AGAIN:      return "Host not found, try again";
825   case WSANO_RECOVERY:    return "Unrecoverable error in call to nameserver";
826   case WSANO_DATA:        return "No data record of requested type";
827
828   default:
829     return NULL;
830   }
831 }
832
833 /* Return the error message corresponding to ERR.  This is different
834    from Windows libc strerror() in that it handles Winsock errors
835    correctly.  */
836
837 const char *
838 windows_strerror (int err)
839 {
840   const char *p;
841   if (err >= 0 && err < sys_nerr)
842     return strerror (err);
843   else if ((p = get_winsock_error (err)) != NULL)
844     return p;
845   else
846     {
847       static char buf[32];
848       snprintf (buf, sizeof (buf), "Unknown error %d (%#x)", err, err);
849       return buf;
850     }
851 }
852 \f
853 #ifdef ENABLE_IPV6
854 /* An IPv6-only inet_ntop that prints with WSAAddressToString.  (Wget
855    uses inet_ntoa for IPv4 addresses -- see print_address.)  Prototype
856    complies with POSIX 1003.1-2004.  */
857
858 const char *
859 inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
860 {
861   struct sockaddr_in6 sin6;
862   DWORD dstlen = cnt;
863
864   assert (af == AF_INET6);
865   xzero (sin6);
866   sin6.sin6_family = AF_INET6;
867   sin6.sin6_addr = *(struct in6_addr *) src;
868   if (WSAAddressToString ((struct sockaddr *) &sin6, sizeof (sin6),
869                           NULL, dst, &dstlen) != 0)
870     {
871       errno = WSAGetLastError();
872       return NULL;
873     }
874   return (const char *) dst;
875 }
876 #endif