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