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