summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@microsoft.com>2013-08-16 13:31:24 -0500
committerEdward Thomson <ethomson@microsoft.com>2013-08-19 17:21:35 -0500
commit238b761491bee6b03f95fca9037b8dff8cced7e7 (patch)
tree9f6ee45fc3286c8c5e9f66fce9d57c2c012f7a42 /src
parent25b2a555380a7b3066f3578c283a8f4d1d5dad12 (diff)
downloadlibgit2-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.h7
-rw-r--r--src/win32/posix_w32.c60
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;
}