diff options
| author | Edward Thomson <ethomson@microsoft.com> | 2013-08-16 13:31:24 -0500 |
|---|---|---|
| committer | Edward Thomson <ethomson@microsoft.com> | 2013-08-19 17:21:35 -0500 |
| commit | 238b761491bee6b03f95fca9037b8dff8cced7e7 (patch) | |
| tree | 9f6ee45fc3286c8c5e9f66fce9d57c2c012f7a42 /src | |
| parent | 25b2a555380a7b3066f3578c283a8f4d1d5dad12 (diff) | |
| download | libgit2-238b761491bee6b03f95fca9037b8dff8cced7e7.tar.gz | |
Fix p_inet_pton on windows
p_inet_pton on Windows should set errno properly for callers.
Rewrite p_inet_pton to handle error cases correctly and add
test cases to exercise this function.
Diffstat (limited to 'src')
| -rw-r--r-- | src/win32/posix.h | 7 | ||||
| -rw-r--r-- | src/win32/posix_w32.c | 60 |
2 files changed, 35 insertions, 32 deletions
diff --git a/src/win32/posix.h b/src/win32/posix.h index 5f924a026..24cba23e0 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -12,6 +12,13 @@ #include "utf-conv.h" #include "dir.h" +/* define some standard errnos that the runtime may be missing. for example, + * mingw lacks EAFNOSUPPORT. */ + +#ifndef EAFNOSUPPORT +# define EAFNOSUPPORT (INT_MAX-1) +#endif + GIT_INLINE(int) p_link(const char *old, const char *new) { GIT_UNUSED(old); diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 087adcce3..2f490529c 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -518,44 +518,40 @@ p_gmtime_r (const time_t *timer, struct tm *result) return result; } -int p_inet_pton(int af, const char* src, void* dst) +int p_inet_pton(int af, const char *src, void *dst) { - union { - struct sockaddr_in6 sin6; - struct sockaddr_in sin; - } sa; - int srcsize; + struct sockaddr_storage sin; + void *addr; + int sin_len = sizeof(struct sockaddr_storage), addr_len; + int error = 0; - switch(af) - { - case AF_INET: - sa.sin.sin_family = AF_INET; - srcsize = (int)sizeof(sa.sin); - break; - case AF_INET6: - sa.sin6.sin6_family = AF_INET6; - srcsize = (int)sizeof(sa.sin6); - break; - default: - errno = WSAEPFNOSUPPORT; - return -1; + if (af == AF_INET) { + addr = &((struct sockaddr_in *)&sin)->sin_addr; + addr_len = sizeof(struct in_addr); + } else if (af == AF_INET6) { + addr = &((struct sockaddr_in6 *)&sin)->sin6_addr; + addr_len = sizeof(struct in6_addr); + } else { + errno = EAFNOSUPPORT; + return -1; } - if (WSAStringToAddress((LPSTR)src, af, NULL, (struct sockaddr *) &sa, &srcsize) != 0) - { - errno = WSAGetLastError(); - return -1; + if ((error = WSAStringToAddressA((LPSTR)src, af, NULL, (LPSOCKADDR)&sin, &sin_len)) == 0) { + memcpy(dst, addr, addr_len); + return 1; } - switch(af) - { - case AF_INET: - memcpy(dst, &sa.sin.sin_addr, sizeof(sa.sin.sin_addr)); - break; - case AF_INET6: - memcpy(dst, &sa.sin6.sin6_addr, sizeof(sa.sin6.sin6_addr)); - break; + switch(WSAGetLastError()) { + case WSAEINVAL: + return 0; + case WSAEFAULT: + errno = ENOSPC; + return -1; + case WSA_NOT_ENOUGH_MEMORY: + errno = ENOMEM; + return -1; } - return 1; + errno = EINVAL; + return -1; } |
