[Pkg-gnu-smalltalk-devel] Bug#497033: gnu-smalltalk: FTBFS on GNU/kFreeBSD
Paolo Bonzini
bonzini at gnu.org
Fri Aug 29 13:03:03 UTC 2008
> This structure have to be different on BSDs.
> I am unable to fix it my self.
I see why the fix in experimental does not work. Apparently BSD systems
actually do not care much about the content of sa_len, it's just that it
is there. I had tested the fix with Mac OS on a big-endian PowerPC. So
sa_len was always 0, but sa_family was set correctly. On little-endian
systems it's the other way round, and sa_family is set incorrectly to 0.
I'm now always passing to C sockaddrs with sa_len, and removing the
sa_len on platforms that do not have it.
2008-08-29 Paolo Bonzini <bonzini at gnu.org>
* IP6SocketImpl.st: Fill in sa_len dutifully for BSD systems.
* IPSocketImpl.st: Fill in sa_len dutifully for BSD systems.
* UnixSocketImpl.st: Fill in sa_len dutifully for BSD systems.
* sockets.c: Undo the above dutifully for non-BSD systems.
diff --git a/build-aux/sockets.m4 b/build-aux/sockets.m4
index 3020534..2f62e83 100644
--- a/build-aux/sockets.m4
+++ b/build-aux/sockets.m4
@@ -25,6 +25,9 @@ AC_CHECK_MEMBER([struct addrinfo.ai_family],
[Define if your system's netdb.h has struct
addrinfo])], [],
[#include <netdb.h>])
+dnl This is wrong for Windows, but anyway Windows does not have sa_len
+AC_CHECK_MEMBERS([struct sockaddr.sa_len], , , [#include <sys/socket.h>])
+
if test "$ac_cv_lib_ws2_32_listen" = "yes"; then
gst_cv_sockets=yes
fi
diff --git a/packages/sockets/IP6SocketImpl.st
b/packages/sockets/IP6SocketImpl.st
index 4c043a2..d437632 100644
--- a/packages/sockets/IP6SocketImpl.st
+++ b/packages/sockets/IP6SocketImpl.st
@@ -248,8 +248,9 @@ stream (TCP), datagram (UDP) and raw sockets.'>
with: address
startingAt: 1;
- "Write sin_family = AF_INET in host order"
- shortAt: 1 put: self class addressFamily;
+ "Write sin_len and sin_family = AF_INET6"
+ at: 1 put: 28;
+ at: 2 put: self class addressFamily;
"Write sin_port in network order (big endian)"
at: 3 put: port // 256;
diff --git a/packages/sockets/IPSocketImpl.st
b/packages/sockets/IPSocketImpl.st
index b298d80..f1837a7 100644
--- a/packages/sockets/IPSocketImpl.st
+++ b/packages/sockets/IPSocketImpl.st
@@ -315,8 +315,9 @@ stream (TCP), datagram (UDP) and raw sockets.'>
with: address
startingAt: 1;
- "Write sin_family = AF_INET in host order"
- shortAt: 1 put: self class addressFamily;
+ "Write sin_len and sin_family = AF_INET"
+ at: 1 put: 16;
+ at: 2 put: self class addressFamily;
"Write sin_port in network order (big endian)"
at: 3 put: port // 256;
diff --git a/packages/sockets/UnixSocketImpl.st
b/packages/sockets/UnixSocketImpl.st
index 794c5ef..58b6ddd 100644
--- a/packages/sockets/UnixSocketImpl.st
+++ b/packages/sockets/UnixSocketImpl.st
@@ -138,8 +138,9 @@ a String or a File object.
portString size > 108
ifTrue: [self error: 'socket path too long'].
^(ByteArray new: 110)
- "Write sin_family = AF_INET in host order"
- shortAt: 1 put: self class addressFamily;
+ "Write sin_len and sin_family = AF_UNIX"
+ at: 1 put: portString size + 2;
+ at: 2 put: self class addressFamily;
replaceFrom: 3 to: portString size + 2 with: portString
startingAt: 1;
yourself
]
diff --git a/packages/sockets/sockets.c b/packages/sockets/sockets.c
index a7cc1a1..c34b1b5 100644
--- a/packages/sockets/sockets.c
+++ b/packages/sockets/sockets.c
@@ -270,9 +270,25 @@ mySocket (int domain, int type, int protocol)
return fd;
}
+
+/* BSD systems have sa_len, others have not. Smalltalk will always
+ write sockaddr structs as if they had it. So for Linux and Winsock
+ we read the second byte (sa_family on BSD systems) and write it in the
+ entire sa_family field. */
+static inline void
+fix_sockaddr (struct sockaddr *sockaddr)
+{
+#ifndef HAVE_STRUCT_SOCKADDR_SA_LEN
+ /* Make sure sa_family is a short. */
+ char verify[sizeof (sockaddr->sa_family) == 2 ? 1 : -1];
+
+ sockaddr->sa_family = ((unsigned char *) sockaddr)[1];
+#endif
+}
+
/* Same as connect, but forces the socket to be in non-blocking mode */
static void
-myConnect (int fd, const struct sockaddr *sockaddr, int len)
+myConnect (int fd, struct sockaddr *sockaddr, int len)
{
SOCKET sock = FD_TO_SOCKET (fd);
#ifdef __MSVCRT__
@@ -286,6 +302,7 @@ myConnect (int fd, const struct sockaddr *sockaddr,
int len)
fcntl (sock, F_SETFL, oldflags | O_NONBLOCK);
#endif
+ fix_sockaddr (sockaddr);
connect (sock, sockaddr, len);
if (is_socket_error (EINPROGRESS))
errno = 0;
@@ -299,8 +316,9 @@ myAccept (int fd, struct sockaddr *addr, int *addrlen)
}
static int
-myBind (int fd, const struct sockaddr *addr, int addrlen)
+myBind (int fd, struct sockaddr *addr, int addrlen)
{
+ fix_sockaddr (addr);
return bind (FD_TO_SOCKET (fd), addr, addrlen);
}
@@ -345,8 +363,9 @@ myRecvfrom (int fd, char *buf, int len, int flags,
struct sockaddr *from,
static int
mySendto (int fd, const char *buf, int len, int flags,
- const struct sockaddr *to, int tolen)
+ struct sockaddr *to, int tolen)
{
+ fix_sockaddr (to);
return sendto (FD_TO_SOCKET (fd), buf, len, flags, to, tolen);
}
@@ -355,6 +374,7 @@ mySetsockopt (int fd, int level, int optname, const
char *optval, int optlen)
{
return setsockopt (FD_TO_SOCKET (fd), level, optname, optval, optlen);
}
+
static int
getSoError (int fd)
{
Blaaargh.
Paolo
More information about the Pkg-gnu-smalltalk-devel
mailing list