1
0
mirror of https://github.com/moparisthebest/wget synced 2024-07-03 16:38:41 -04:00

[svn] Store errors for Winsock calls in errno. Provide a version of strerror

that handles Winsock errors.
This commit is contained in:
hniksic 2005-03-06 08:36:45 -08:00
parent f3aece8d22
commit 8612bacf0a
3 changed files with 163 additions and 4 deletions

View File

@ -1,3 +1,12 @@
2005-03-06 Hrvoje Niksic <hniksic@xemacs.org>
* mswindows.c: Provide wrappers to Winsock functions that set
errno to WSAGetLastError() in case of failure. Also provide a
Windows-specific version of strerror.
* mswindows.h: Wrap calls to socket, bind, connect, recv, send,
select, getsockname, getpeername, and setsockopt.
2005-03-06 Hrvoje Niksic <hniksic@xemacs.org>
* url.c (url_parse): Reject port numbers larger than 65535. We

View File

@ -48,6 +48,8 @@ so, delete this exception statement from your version. */
# endif
#endif
#define INHIBIT_WRAP /* avoid wrapping of socket, bind, ... */
#include "wget.h"
#include "utils.h"
#include "url.h"
@ -210,7 +212,7 @@ str_to_int64 (const char *nptr, char **endptr, int base)
#endif /* !defined(__BORLANDC__) && (!defined(_MSC_VER) || _MSC_VER >= 1300) */
void
windows_main_junk (int *argc, char **argv, char **exec_name)
windows_main (int *argc, char **argv, char **exec_name)
{
char *p;
@ -335,7 +337,7 @@ fake_fork (void)
char *name;
BOOL rv;
event = section = pi.hProcess = pi.hThread = NULL;
section = pi.hProcess = pi.hThread = NULL;
/* Get the fully qualified name of our executable. This is more reliable
than using argv[0]. */
@ -694,7 +696,7 @@ run_with_timeout (double seconds, void (*fun) (void *), void *arg)
static HANDLE thread_hnd = NULL;
struct thread_data thread_arg;
DWORD thread_id;
int rc = 0;
int rc;
DEBUGP (("seconds %.2f, ", seconds));
@ -738,3 +740,117 @@ run_with_timeout (double seconds, void (*fun) (void *), void *arg)
thread_hnd = NULL;
return rc;
}
/* Wget expects network calls such as bind, connect, etc., to set errno.
To achieve that, we place Winsock calls in wrapper functions that, in
case of error, sets errno to the value of GetLastError(). In addition,
we provide a wrapper around strerror, which recognizes Winsock errors
and prints the appropriate error message. */
/* Define a macro that creates a function definition that wraps FUN into
a function that sets errno the way the rest of the code expects. */
#define WRAP(fun, decl, call) int wrap_##fun decl { \
int retval = fun call; \
if (retval < 0) \
errno = WSAGetLastError (); \
return retval; \
}
WRAP (socket, (int domain, int type, int protocol), (domain, type, protocol))
WRAP (bind, (int s, struct sockaddr *a, int alen), (s, a, alen))
WRAP (connect, (int s, const struct sockaddr *a, int alen), (s, a, alen))
WRAP (recv, (int s, void *buf, int len, int flags), (s, buf, len, flags))
WRAP (send, (int s, const void *buf, int len, int flags), (s, buf, len, flags))
WRAP (select, (int n, fd_set *r, fd_set *w, fd_set *e, const struct timeval *tm),
(n, r, w, e, tm))
WRAP (getsockname, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
WRAP (getpeername, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
WRAP (setsockopt, (int s, int level, int opt, const void *val, int len),
(s, level, opt, val, len))
/* Return the text of the error message for Winsock error WSERR. */
static const char *
get_winsock_error (int wserr)
{
switch (wserr) {
case WSAEINTR: return "Interrupted system call";
case WSAEBADF: return "Bad file number";
case WSAEACCES: return "Permission denied";
case WSAEFAULT: return "Bad address";
case WSAEINVAL: return "Invalid argument";
case WSAEMFILE: return "Too many open files";
case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
case WSAEINPROGRESS: return "Operation now in progress";
case WSAEALREADY: return "Operation already in progress";
case WSAENOTSOCK: return "Socket operation on nonsocket";
case WSAEDESTADDRREQ: return "Destination address required";
case WSAEMSGSIZE: return "Message too long";
case WSAEPROTOTYPE: return "Protocol wrong type for socket";
case WSAENOPROTOOPT: return "Bad protocol option";
case WSAEPROTONOSUPPORT: return "Protocol not supported";
case WSAESOCKTNOSUPPORT: return "Socket type not supported";
case WSAEOPNOTSUPP: return "Operation not supported";
case WSAEPFNOSUPPORT: return "Protocol family not supported";
case WSAEAFNOSUPPORT: return "Address family not supported by protocol family";
case WSAEADDRINUSE: return "Address already in use";
case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
case WSAENETDOWN: return "Network is down";
case WSAENETUNREACH: return "Network is unreachable";
case WSAENETRESET: return "Network dropped connection on reset";
case WSAECONNABORTED: return "Software caused connection abort";
case WSAECONNRESET: return "Connection reset by peer";
case WSAENOBUFS: return "No buffer space available";
case WSAEISCONN: return "Socket is already connected";
case WSAENOTCONN: return "Socket is not connected";
case WSAESHUTDOWN: return "Cannot send after socket shutdown";
case WSAETOOMANYREFS: return "Too many references";
case WSAETIMEDOUT: return "Connection timed out";
case WSAECONNREFUSED: return "Connection refused";
case WSAELOOP: return "Too many levels of symbolic links";
case WSAENAMETOOLONG: return "File name too long";
case WSAEHOSTDOWN: return "Host is down";
case WSAEHOSTUNREACH: return "No route to host";
case WSAENOTEMPTY: return "Not empty";
case WSAEPROCLIM: return "Too many processes";
case WSAEUSERS: return "Too many users";
case WSAEDQUOT: return "Bad quota";
case WSAESTALE: return "Something is stale";
case WSAEREMOTE: return "Remote error";
case WSAEDISCON: return "Disconnected";
/* Extended Winsock errors */
case WSASYSNOTREADY: return "Winsock library is not ready";
case WSANOTINITIALISED: return "Winsock library not initalised";
case WSAVERNOTSUPPORTED: return "Winsock version not supported";
case WSAHOST_NOT_FOUND: return "Host not found";
case WSATRY_AGAIN: return "Host not found, try again";
case WSANO_RECOVERY: return "Unrecoverable error in call to nameserver";
case WSANO_DATA: return "No data record of requested type";
default:
return NULL;
}
}
/* Return the error message corresponding to ERR. This is different
from Windows libc strerror() in that it handles Winsock errors
correctly. */
const char *
windows_strerror (int err)
{
const char *p;
if (err >= 0 && err < sys_nerr)
return strerror (err);
else if ((p = get_winsock_error (err)) != NULL)
return p;
else
{
static char buf[32];
snprintf (buf, sizeof (buf), "Unknown error %d (%#x)", err, err);
return buf;
}
}

View File

@ -130,6 +130,40 @@ __int64 str_to_int64 (const char *, char **, int);
# define mkdir(a, b) mkdir(a)
#endif /* __BORLANDC__ */
#ifndef INHIBIT_WRAP
/* Winsock functions don't set errno, so we provide wrappers
that do. */
#define socket wrap_socket
#define bind wrap_bind
#define connect wrap_connect
#define recv wrap_recv
#define send wrap_send
#define select wrap_select
#define getsockname wrap_getsockname
#define getpeername wrap_getpeername
#define setsockopt wrap_setsockopt
#endif /* not INHIBIT_WRAP */
int wrap_socket (int, int, int);
int wrap_bind (int, struct sockaddr *, int);
int wrap_connect (int, const struct sockaddr *, int);
int wrap_recv (int, void *, int, int);
int wrap_send (int, const void *, int, int);
int wrap_select (int, fd_set *, fd_set *, fd_set *, const struct timeval *);
int wrap_getsockname (int, struct sockaddr *, int *);
int wrap_getpeername (int, struct sockaddr *, int *);
int wrap_setsockopt (int, int, int, const void *, int);
/* Finally, provide a private version of strerror that does the
right thing with Winsock errors. */
#ifndef INHIBIT_WRAP
# define strerror windows_strerror
#endif
const char *windows_strerror (int);
/* Declarations of various socket errors: */
#define EWOULDBLOCK WSAEWOULDBLOCK
@ -181,7 +215,7 @@ void ws_startup (void);
void ws_changetitle (const char *);
void ws_percenttitle (double);
char *ws_mypath (void);
void windows_main_junk (int *, char **, char **);
void windows_main (int *, char **, char **);
/* Things needed for IPv6; missing in <ws2tcpip.h>. */
#ifdef ENABLE_IPV6