Patchwork libgo patch committed: Clean up syscalls, add some Solaris support

login
register
mail settings
Submitter Ian Taylor
Date Jan. 13, 2011, 5:17 a.m.
Message ID <mcrd3o1tm9p.fsf@google.com>
Download mbox | patch
Permalink /patch/78656/
State New
Headers show

Comments

Ian Taylor - Jan. 13, 2011, 5:17 a.m.
This patch, partly due to Rainer Orth, cleans up the libgo syscalls
directory a bit to remove some redundancy, and adds Solaris support.
Bootstrapped and ran libgo testsuite on x86_64-unknown-linux-gnu in both
32-bit and 64-bit mode.  Committed to mainline.

Ian

Patch

diff -r 169c58c802a1 libgo/Makefile.am
--- a/libgo/Makefile.am	Wed Jan 12 15:04:36 2011 -0800
+++ b/libgo/Makefile.am	Wed Jan 12 18:09:18 2011 -0800
@@ -596,10 +596,17 @@ 
 if LIBGO_IS_RTEMS
 go_net_fd_os_file = go/net/fd_rtems.go
 go_net_newpollserver_file = go/net/newpollserver_rtems.go
-else
+else # !LIBGO_IS_RTEMS
+if LIBGO_IS_LINUX
 go_net_fd_os_file = go/net/fd_linux.go
 go_net_newpollserver_file = go/net/newpollserver.go
-endif
+else # !LIBGO_IS_LINUX && !LIBGO_IS_RTEMS
+# By default use select with pipes.  Most systems should have
+# something better.
+go_net_fd_os_file = go/net/fd_rtems.go
+go_net_newpollserver_file = go/net/newpollserver.go
+endif # !LIBGO_IS_LINUX
+endif # !LIBGO_IS_RTEMS
 
 go_net_files = \
 	go/net/dial.go \
@@ -1019,33 +1026,92 @@ 
 go_testing_script_files = \
 	go/testing/script/script.go
 
+# Define Syscall and Syscall6.
+if LIBGO_IS_RTEMS
+syscall_syscall_file = syscalls/syscall_stubs.go
+else
+syscall_syscall_file = syscalls/syscall.go
+endif
+
+# Declare libc functions that vary for largefile systems.
+if LIBGO_IS_LINUX
+# Always use lseek64 on GNU/Linux.
+syscall_filesize_file = syscalls/sysfile_largefile.go
+else # !LIBGO_IS_LINUX
+if LIBGO_IS_SOLARIS
+if LIBGO_IS_386
+# Use lseek64 on 386 Solaris.
+syscall_filesize_flie = syscalls/sysfile_largefile.go
+else # !LIBGO_IS_LINUX && LIBGO_IS_SOLARIS && !LIBGO_IS_386
+# Use lseek on amd64 Solaris.
+syscall_filesize_flie = syscalls/sysfile_regfile.go
+endif # !LIBGO_IS_386
+else # !LIBGO_IS_LINUX && !LIBGO_IS_SOLARIS
+# Use lseek by default.
+syscall_filesize_file = syscalls/sysfile_regfile.go
+endif # !LIBGO_IS_SOLARIS
+endif # !LIBGO_IS_LINUX
+
+
+# Define ForkExec, PtraceForkExec, Exec, and Wait4.
 if LIBGO_IS_RTEMS
 syscall_exec_os_file = syscalls/exec_stubs.go
-syscall_socket_os_file = syscalls/socket_bsd.go
-syscall_socket_epoll_file =
-syscall_sysfile_os_file = syscalls/sysfile_rtems.go
-syscall_syscall_file = syscalls/syscall_stubs.go
+else
+syscall_exec_os_file = syscalls/exec.go
+endif
+
+# Define Sleep.
+if LIBGO_IS_RTEMS
+syscall_sleep_file = syscalls/sleep_rtems.go
+else
+syscall_sleep_file = syscalls/sleep_select.go
+endif
+
+# Define Errstr.
+if LIBGO_IS_RTEMS
 syscall_errstr_file = syscalls/errstr_rtems.go
+else
+syscall_errstr_file = syscalls/errstr.go
+endif
+
+# Declare libc_strerror_r which is the Go name for strerror_r.
+if LIBGO_IS_RTEMS
+# RTEMS uses newlib in which strerror_r returns char *.
 syscall_errstr_decl_file = syscalls/errstr_decl_rtems.go
 else
-syscall_exec_os_file = syscalls/exec.go
-syscall_socket_os_file = syscalls/socket_linux.go
-syscall_socket_epoll_file = syscalls/socket_epoll.go
-syscall_sysfile_os_file = syscalls/sysfile_linux.go
-syscall_syscall_file = syscalls/syscall.go
-syscall_errstr_file = syscalls/errstr.go
 if LIBGO_IS_LINUX
+# In Linux the POSIX strerror_r is called __xpg_strerror_r.
 syscall_errstr_decl_file = syscalls/errstr_decl_linux.go
 else
+# On other systems we hope strerror_r is just strerror_r.
 syscall_errstr_decl_file = syscalls/errstr_decl.go
 endif
 endif
 
+# Define socket sizes and types.
+if LIBGO_IS_LINUX
+syscall_socket_os_file = syscalls/socket_linux.go
+else
+if LIBGO_IS_SOLARIS
+syscall_socket_os_file = syscalls/socket_solaris.go
+else
+syscall_socket_os_file = syscalls_socket_bsd.go
+endif
+endif
+
+# Support for epoll.
+if LIBGO_IS_LINUX
+syscall_socket_epoll_file = syscalls/socket_epoll.go
+else
+syscall_socket_epoll_file =
+endif
+
 syscall_arch.go: s-syscall_arch; @true
 s-syscall_arch: Makefile
 	rm -f syscall_arch.go.tmp
 	echo "package syscall" > syscall_arch.go.tmp
 	echo 'const ARCH = "'$(GOARCH)'"' >> syscall_arch.go.tmp
+	echo 'const OS = "'$(GOOS)'"' >> syscall_arch.go.tmp
 	$(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go
 	$(STAMP) $@
 
@@ -1054,6 +1120,8 @@ 
 	$(syscall_errstr_decl_file) \
 	syscalls/exec_helpers.go \
 	$(syscall_exec_os_file) \
+	$(syscall_filesize_file) \
+	$(syscall_sleep_file) \
 	syscalls/socket.go \
 	$(syscall_socket_os_file) \
 	$(syscall_socket_epoll_file) \
@@ -1063,7 +1131,6 @@ 
 	syscalls/syscall_$(GOOS).go \
 	syscalls/syscall_$(GOOS)_$(GOARCH).go \
 	syscalls/sysfile_posix.go \
-	$(syscall_sysfile_os_file) \
 	sysinfo.go \
 	syscall_arch.go
 go_syscall_c_files = \
@@ -2232,7 +2299,7 @@ 
 .PHONY: testing/script/check
 
 sysinfo.go: $(srcdir)/mksysinfo.sh config.h
-	$(SHELL) $(srcdir)/mksysinfo.sh
+	CC="$(CC)" $(SHELL) $(srcdir)/mksysinfo.sh
 syscalls/libsyscall.a: $(go_syscall_files) $(go_syscall_c_files) sync.gox
 	rm -f syscall.gox syscalls/libsyscall.a
 	test -d syscalls || $(MKDIR_P) syscalls
diff -r 169c58c802a1 libgo/syscalls/errstr.go
--- a/libgo/syscalls/errstr.go	Wed Jan 12 15:04:36 2011 -0800
+++ b/libgo/syscalls/errstr.go	Wed Jan 12 18:09:18 2011 -0800
@@ -6,11 +6,6 @@ 
 
 package syscall
 
-const ENONE = 0
-
-func GetErrno() int
-func SetErrno(int)
-
 func Errstr(errno int) string {
 	for len := Size_t(128); ; len *= 2 {
 		b := make([]byte, len)
diff -r 169c58c802a1 libgo/syscalls/errstr_rtems.go
--- a/libgo/syscalls/errstr_rtems.go	Wed Jan 12 15:04:36 2011 -0800
+++ b/libgo/syscalls/errstr_rtems.go	Wed Jan 12 18:09:18 2011 -0800
@@ -6,11 +6,6 @@ 
 
 package syscall
 
-const ENONE = 0
-
-func GetErrno() int
-func SetErrno(int)
-
 func Errstr(errno int) string {
 	for len := Size_t(128); ; len *= 2 {
 		b := make([]byte, len+1)
diff -r 169c58c802a1 libgo/syscalls/sleep_rtems.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgo/syscalls/sleep_rtems.go	Wed Jan 12 18:09:18 2011 -0800
@@ -0,0 +1,17 @@ 
+// sleep_rtems.go -- Sleep on RTEMS.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+func libc_nanosleep(req *Timespec, rem *Timespec) int __asm__ ("nanosleep")
+
+func Sleep(nsec int64) (errno int) {
+	errno = 0
+	ts := NsecToTimespec(nsec)
+	r := libc_nanosleep(&ts, nil)
+	if r < 0 {
+		errno = GetErrno()
+	}
+	return
+}
diff -r 169c58c802a1 libgo/syscalls/sleep_select.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgo/syscalls/sleep_select.go	Wed Jan 12 18:09:18 2011 -0800
@@ -0,0 +1,13 @@ 
+// sleep_select.go -- Sleep using select.
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+func Sleep(nsec int64) (errno int) {
+	tv := NsecToTimeval(nsec);
+	n, err := Select(0, nil, nil, nil, &tv);
+	return err;
+}
diff -r 169c58c802a1 libgo/syscalls/socket.go
--- a/libgo/syscalls/socket.go	Wed Jan 12 15:04:36 2011 -0800
+++ b/libgo/syscalls/socket.go	Wed Jan 12 18:09:18 2011 -0800
@@ -12,10 +12,6 @@ 
 
 import "unsafe"
 
-const SizeofSockaddrInet4 = 16
-const SizeofSockaddrInet6 = 28
-const SizeofSockaddrUnix = 110
-
 type RawSockaddrAny struct {
 	Addr RawSockaddr;
 	Pad [12]int8;
@@ -53,6 +49,91 @@ 
 	Linger int32;
 }
 
+func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+	if sa.Port < 0 || sa.Port > 0xFFFF {
+		return nil, 0, EINVAL;
+	}
+	sa.raw.Family = AF_INET;
+	n := sa.raw.setLen()
+	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
+	p[0] = byte(sa.Port>>8);
+	p[1] = byte(sa.Port);
+	for i := 0; i < len(sa.Addr); i++ {
+		sa.raw.Addr[i] = sa.Addr[i];
+	}
+	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, 0;
+}
+
+func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+	if sa.Port < 0 || sa.Port > 0xFFFF {
+		return nil, 0, EINVAL;
+	}
+	sa.raw.Family = AF_INET6;
+	n := sa.raw.setLen()
+	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
+	p[0] = byte(sa.Port>>8);
+	p[1] = byte(sa.Port);
+	for i := 0; i < len(sa.Addr); i++ {
+		sa.raw.Addr[i] = sa.Addr[i];
+	}
+	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, 0;
+}
+
+func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+	name := sa.Name;
+	n := len(name);
+	if n >= len(sa.raw.Path) || n == 0 {
+		return nil, 0, EINVAL;
+	}
+	sa.raw.Family = AF_UNIX;
+	sa.raw.setLen(n)
+	for i := 0; i < n; i++ {
+		sa.raw.Path[i] = int8(name[i]);
+	}
+	if sa.raw.Path[0] == '@' {
+		sa.raw.Path[0] = 0;
+	}
+
+	// length is family (uint16), name, NUL.
+	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), 2 + Socklen_t(n) + 1, 0;
+}
+
+func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
+	switch rsa.Addr.Family {
+	case AF_UNIX:
+		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
+		sa := new(SockaddrUnix)
+		n, err := pp.getLen()
+		if err != 0 {
+			return nil, err
+		}
+		bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]));
+		sa.Name = string(bytes[0:n]);
+		return sa, 0;
+
+	case AF_INET:
+		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
+		sa := new(SockaddrInet4);
+		p := (*[2]byte)(unsafe.Pointer(&pp.Port));
+		sa.Port = int(p[0])<<8 + int(p[1]);
+		for i := 0; i < len(sa.Addr); i++ {
+			sa.Addr[i] = pp.Addr[i];
+		}
+		return sa, 0;
+
+	case AF_INET6:
+		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
+		sa := new(SockaddrInet6);
+		p := (*[2]byte)(unsafe.Pointer(&pp.Port));
+		sa.Port = int(p[0])<<8 + int(p[1]);
+		for i := 0; i < len(sa.Addr); i++ {
+			sa.Addr[i] = pp.Addr[i];
+		}
+		return sa, 0;
+	}
+	return nil, EAFNOSUPPORT;
+}
+
 func libc_accept(fd int, sa *RawSockaddrAny, len *Socklen_t) int __asm__ ("accept");
 func libc_bind(fd int, sa *RawSockaddrAny, len Socklen_t) int __asm__ ("bind");
 func libc_connect(fd int, sa *RawSockaddrAny, len Socklen_t) int __asm__ ("connect");
diff -r 169c58c802a1 libgo/syscalls/socket_bsd.go
--- a/libgo/syscalls/socket_bsd.go	Wed Jan 12 15:04:36 2011 -0800
+++ b/libgo/syscalls/socket_bsd.go	Wed Jan 12 18:09:18 2011 -0800
@@ -4,13 +4,11 @@ 
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Low-level socket interface.
-// Only for implementing net package.
-// DO NOT USE DIRECTLY.
-
 package syscall
 
-import "unsafe"
+const SizeofSockaddrInet4 = 16
+const SizeofSockaddrInet6 = 28
+const SizeofSockaddrUnix = 110
 
 type RawSockaddrInet4 struct {
 	Len uint8;
@@ -20,6 +18,11 @@ 
 	Zero [8]uint8;
 }
 
+func (sa *RawSockaddrInet4) setLen() Socklen_t {
+	sa.Len = SizeofSockaddrInet4
+	return SizeofSockaddrInet4
+}
+
 type RawSockaddrInet6 struct {
 	Len uint8;
 	Family uint8;
@@ -29,110 +32,42 @@ 
 	Scope_id uint32;
 }
 
+func (sa *RawSockaddrInet6) setLen() Socklen_t {
+	sa.raw.Len = SizeofSockaddrInet6
+	return SizeofSockaddrInet6
+}
+
 type RawSockaddrUnix struct {
 	Len uint8;
 	Family uint8;
 	Path [108]int8;
 }
 
+func (sa *RawsockaddrUnix) setLen(n int) {
+	sa.Len = uint8(3 + n) // 2 for Family, Len; 1 for NUL.
+}
+
+func (sa *RawsockaddrUnix) getLen() (int, int) {
+	if sa.Len < 3 || sa.Len > SizeofSockaddrUnix {
+		return 0, EINVAL
+	}
+	n := int(sa.Len) - 3 // subtract leading Family, Len, terminating NUL.
+	for i := 0; i < n; i++ {
+		if sa.Path[i] == 0 {
+			// found early NUL; assume Len is overestimating.
+			n = i
+			break
+		}
+	}
+	return n, 0
+}
+
 type RawSockaddr struct {
 	Len uint8;
 	Family uint8;
 	Data [14]int8;
 }
 
-func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
-	if sa.Port < 0 || sa.Port > 0xFFFF {
-		return nil, 0, EINVAL;
-	}
-	sa.raw.Len = SizeofSockaddrInet4;
-	sa.raw.Family = AF_INET;
-	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
-	p[0] = byte(sa.Port>>8);
-	p[1] = byte(sa.Port);
-	for i := 0; i < len(sa.Addr); i++ {
-		sa.raw.Addr[i] = sa.Addr[i];
-	}
-	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), Socklen_t(sa.raw.Len), 0;
-}
-
-func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
-	if sa.Port < 0 || sa.Port > 0xFFFF {
-		return nil, 0, EINVAL;
-	}
-	sa.raw.Len = SizeofSockaddrInet6;
-	sa.raw.Family = AF_INET6;
-	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
-	p[0] = byte(sa.Port>>8);
-	p[1] = byte(sa.Port);
-	for i := 0; i < len(sa.Addr); i++ {
-		sa.raw.Addr[i] = sa.Addr[i];
-	}
-	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), Socklen_t(sa.raw.Len), 0;
-}
-
-func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
-	name := sa.Name;
-	n := len(name);
-	if n >= len(sa.raw.Path) || n == 0 {
-		return nil, 0, EINVAL;
-	}
-	sa.raw.Len = byte(3 + n); // 2 for Family, Len; 1 for NUL.
-	sa.raw.Family = AF_UNIX;
-	for i := 0; i < n; i++ {
-		sa.raw.Path[i] = int8(name[i]);
-	}
-	if sa.raw.Path[0] == '@' {
-		sa.raw.Path[0] = 0;
-	}
-
-	// length is family, name, NUL.
-	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), Socklen_t(sa.raw.Len), 0;
-}
-
-func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
-	switch rsa.Addr.Family {
-	case AF_UNIX:
-		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
-		if pp.Len < 3 || pp.Len > SizeofSockaddrUnix {
-			return nil, EINVAL
-		}
-		sa := new(SockaddrUnix)
-		n := int(pp.Len) - 3 // subtract leading Family, Len, terminating NUL.
-		for i := 0; i < n; i++ {
-			if pp.Path[i] == 0 {
-				// found early NUL; assume Len is overestimating.
-				n = i
-				break
-			}
-		}
-		bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))
-		sa.Name = string(bytes[0:n])
-		return sa, 0
-
-	case AF_INET:
-		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
-		sa := new(SockaddrInet4);
-		p := (*[2]byte)(unsafe.Pointer(&pp.Port));
-		sa.Port = int(p[0])<<8 + int(p[1]);
-		for i := 0; i < len(sa.Addr); i++ {
-			sa.Addr[i] = pp.Addr[i];
-		}
-		return sa, 0;
-
-	case AF_INET6:
-		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
-		sa := new(SockaddrInet6);
-		p := (*[2]byte)(unsafe.Pointer(&pp.Port));
-		sa.Port = int(p[0])<<8 + int(p[1]);
-		for i := 0; i < len(sa.Addr); i++ {
-			sa.Addr[i] = pp.Addr[i];
-		}
-		return sa, 0;
-	}
-	return nil, EAFNOSUPPORT;
-}
-
 // BindToDevice binds the socket associated with fd to device.
 func BindToDevice(fd int, device string) (errno int) {
 	return ENOSYS
diff -r 169c58c802a1 libgo/syscalls/socket_linux.go
--- a/libgo/syscalls/socket_linux.go	Wed Jan 12 15:04:36 2011 -0800
+++ b/libgo/syscalls/socket_linux.go	Wed Jan 12 18:09:18 2011 -0800
@@ -4,14 +4,11 @@ 
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Low-level socket interface.
-// Only for implementing net package.
-
-// DO NOT USE DIRECTLY.
-
 package syscall
 
-import "unsafe"
+const SizeofSockaddrInet4 = 16
+const SizeofSockaddrInet6 = 28
+const SizeofSockaddrUnix = 110
 
 type RawSockaddrInet4 struct {
 	Family uint16;
@@ -20,6 +17,10 @@ 
 	Zero [8]uint8;
 }
 
+func (sa *RawSockaddrInet4) setLen() Socklen_t {
+	return SizeofSockaddrInet4
+}
+
 type RawSockaddrInet6 struct {
 	Family uint16;
 	Port uint16;
@@ -28,112 +29,46 @@ 
 	Scope_id uint32;
 }
 
+func (sa *RawSockaddrInet6) setLen() Socklen_t {
+	return SizeofSockaddrInet6
+}
+
 type RawSockaddrUnix struct {
 	Family uint16;
 	Path [108]int8;
 }
 
+func (sa *RawSockaddrUnix) setLen(int) {
+}
+
+func (sa *RawSockaddrUnix) getLen() (int, int) {
+	if sa.Path[0] == 0 {
+		// "Abstract" Unix domain socket.
+		// Rewrite leading NUL as @ for textual display.
+		// (This is the standard convention.)
+		// Not friendly to overwrite in place,
+		// but the callers below don't care.
+		sa.Path[0] = '@';
+	}
+
+	// Assume path ends at NUL.
+	// This is not technically the Linux semantics for
+	// abstract Unix domain sockets--they are supposed
+	// to be uninterpreted fixed-size binary blobs--but
+	// everyone uses this convention.
+	n := 0;
+	for n < len(sa.Path) - 3 && sa.Path[n] != 0 {
+		n++;
+	}
+
+	return n, 0
+}
+
 type RawSockaddr struct {
 	Family uint16;
 	Data [14]int8;
 }
 
-func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
-	if sa.Port < 0 || sa.Port > 0xFFFF {
-		return nil, 0, EINVAL;
-	}
-	sa.raw.Family = AF_INET;
-	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
-	p[0] = byte(sa.Port>>8);
-	p[1] = byte(sa.Port);
-	for i := 0; i < len(sa.Addr); i++ {
-		sa.raw.Addr[i] = sa.Addr[i];
-	}
-	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet4, 0;
-}
-
-func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
-	if sa.Port < 0 || sa.Port > 0xFFFF {
-		return nil, 0, EINVAL;
-	}
-	sa.raw.Family = AF_INET6;
-	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
-	p[0] = byte(sa.Port>>8);
-	p[1] = byte(sa.Port);
-	for i := 0; i < len(sa.Addr); i++ {
-		sa.raw.Addr[i] = sa.Addr[i];
-	}
-	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet6, 0;
-}
-
-func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
-	name := sa.Name;
-	n := len(name);
-	if n >= len(sa.raw.Path) || n == 0 {
-		return nil, 0, EINVAL;
-	}
-	sa.raw.Family = AF_UNIX;
-	for i := 0; i < n; i++ {
-		sa.raw.Path[i] = int8(name[i]);
-	}
-	if sa.raw.Path[0] == '@' {
-		sa.raw.Path[0] = 0;
-	}
-
-	// length is family, name, NUL.
-	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), 1 + Socklen_t(n) + 1, 0;
-}
-
-func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
-	switch rsa.Addr.Family {
-	case AF_UNIX:
-		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa));
-		sa := new(SockaddrUnix);
-		if pp.Path[0] == 0 {
-			// "Abstract" Unix domain socket.
-			// Rewrite leading NUL as @ for textual display.
-			// (This is the standard convention.)
-			// Not friendly to overwrite in place,
-			// but the callers below don't care.
-			pp.Path[0] = '@';
-		}
-
-		// Assume path ends at NUL.
-		// This is not technically the Linux semantics for
-		// abstract Unix domain sockets--they are supposed
-		// to be uninterpreted fixed-size binary blobs--but
-		// everyone uses this convention.
-		n := 0;
-		for n < len(pp.Path) - 3 && pp.Path[n] != 0 {
-			n++;
-		}
-		bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]));
-		sa.Name = string(bytes[0:n]);
-		return sa, 0;
-
-	case AF_INET:
-		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
-		sa := new(SockaddrInet4);
-		p := (*[2]byte)(unsafe.Pointer(&pp.Port));
-		sa.Port = int(p[0])<<8 + int(p[1]);
-		for i := 0; i < len(sa.Addr); i++ {
-			sa.Addr[i] = pp.Addr[i];
-		}
-		return sa, 0;
-
-	case AF_INET6:
-		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
-		sa := new(SockaddrInet6);
-		p := (*[2]byte)(unsafe.Pointer(&pp.Port));
-		sa.Port = int(p[0])<<8 + int(p[1]);
-		for i := 0; i < len(sa.Addr); i++ {
-			sa.Addr[i] = pp.Addr[i];
-		}
-		return sa, 0;
-	}
-	return nil, EAFNOSUPPORT;
-}
-
 // BindToDevice binds the socket associated with fd to device.
 func BindToDevice(fd int, device string) (errno int) {
 	return SetsockoptString(fd, SOL_SOCKET, SO_BINDTODEVICE, device)
diff -r 169c58c802a1 libgo/syscalls/socket_solaris.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgo/syscalls/socket_solaris.go	Wed Jan 12 18:09:18 2011 -0800
@@ -0,0 +1,76 @@ 
+// socket_solaris.go -- Socket handling specific to Solaris.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+const SizeofSockaddrInet4 = 16
+const SizeofSockaddrInet6 = 32
+const SizeofSockaddrUnix = 110
+
+type RawSockaddrInet4 struct {
+	Family uint16
+	Port uint16
+	Addr [4]byte /* in_addr */
+	Zero [8]uint8
+}
+
+func (sa *RawSockaddrInet4) setLen() Socklen_t {
+	return SizeofSockaddrInet4
+}
+
+type RawSockaddrInet6 struct {
+	Family uint16
+	Port uint16
+	Flowinfo uint32
+	Addr [16]byte /* in6_addr */
+	Scope_id uint32
+	Src_id uint32
+}
+
+func (sa *RawSockaddrInet6) setLen() Socklen_t {
+	return SizeofSockaddrInet6
+}
+
+type RawSockaddrUnix struct {
+	Family uint16
+	Path [108]int8
+}
+
+func (sa *RawSockaddrUnix) setLen(int) {
+}
+
+func (sa *RawSockaddrUnix) getLen() (int, int) {
+	if sa.Path[0] == 0 {
+		// "Abstract" Unix domain socket.
+		// Rewrite leading NUL as @ for textual display.
+		// (This is the standard convention.)
+		// Not friendly to overwrite in place,
+		// but the callers below don't care.
+		sa.Path[0] = '@'
+	}
+
+	// Assume path ends at NUL.
+	// This is not technically the Linux semantics for
+	// abstract Unix domain sockets--they are supposed
+	// to be uninterpreted fixed-size binary blobs--but
+	// everyone uses this convention.
+	n := 0
+	for n < len(sa.Path) - 3 && sa.Path[n] != 0 {
+		n++
+	}
+
+	return n, 0
+}
+
+type RawSockaddr struct {
+	Family uint16
+	Data [14]int8
+}
+
+// BindToDevice binds the socket associated with fd to device.
+func BindToDevice(fd int, device string) (errno int) {
+	return ENOSYS
+}
diff -r 169c58c802a1 libgo/syscalls/syscall_solaris_386.go
--- a/libgo/syscalls/syscall_solaris_386.go	Wed Jan 12 15:04:36 2011 -0800
+++ b/libgo/syscalls/syscall_solaris_386.go	Wed Jan 12 18:09:18 2011 -0800
@@ -8,8 +8,6 @@ 
 
 import "unsafe"
 
-const ARCH = "386"
-
 // FIXME: ptrace(3C) has this, but exec.go expects the next.
 //func libc_ptrace(request int, pid Pid_t, addr int, data int) int __asm__ ("ptrace")
 
diff -r 169c58c802a1 libgo/syscalls/syscall_solaris_amd64.go
--- a/libgo/syscalls/syscall_solaris_amd64.go	Wed Jan 12 15:04:36 2011 -0800
+++ b/libgo/syscalls/syscall_solaris_amd64.go	Wed Jan 12 18:09:18 2011 -0800
@@ -8,8 +8,6 @@ 
 
 import "unsafe"
 
-const ARCH = "amd64"
-
 // FIXME: ptrace(3C) has this, but exec.go expects the next.
 //func libc_ptrace(request int, pid Pid_t, addr int, data int) int __asm__ ("ptrace")
 
diff -r 169c58c802a1 libgo/syscalls/syscall_unix.go
--- a/libgo/syscalls/syscall_unix.go	Wed Jan 12 15:04:36 2011 -0800
+++ b/libgo/syscalls/syscall_unix.go	Wed Jan 12 18:09:18 2011 -0800
@@ -10,6 +10,11 @@ 
 	Stderr = 2
 )
 
+const ENONE = 0
+
+func GetErrno() int
+func SetErrno(int)
+
 func libc_uname(buf *Utsname) (errno int) __asm__("uname")
 
 func Uname(buf *Utsname) (errno int) {
diff -r 169c58c802a1 libgo/syscalls/sysfile_largefile.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgo/syscalls/sysfile_largefile.go	Wed Jan 12 18:09:18 2011 -0800
@@ -0,0 +1,13 @@ 
+// sysfile_largefile.go -- For systems which use the large file interface.
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+func libc_pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pread64")
+func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pwrite64")
+func libc_lseek(int, Offset_t, int) Offset_t __asm__ ("lseek64")
+func libc_truncate(path *byte, length Offset_t) int __asm__ ("truncate64")
+func libc_ftruncate(fd int, length Offset_t) int __asm__ ("ftruncate64")
diff -r 169c58c802a1 libgo/syscalls/sysfile_linux.go
--- a/libgo/syscalls/sysfile_linux.go	Wed Jan 12 15:04:36 2011 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@ 
-// sysfile_linux.go -- Linux specific file handling.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Support for basic Unix file operations.  This file simply
-// translates from Go data types to Unix data types, and handles
-// errno.  FIXME: This could probably be done mechanically.
-
-package syscall
-
-const OS = "linux"
-
-func libc_pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pread64")
-func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pwrite64")
-func libc_lseek64(int, Offset_t, int) Offset_t __asm__ ("lseek64")
-func libc_truncate64(path *byte, length Offset_t) int __asm__ ("truncate64")
-func libc_ftruncate64(fd int, length Offset_t) int __asm__ ("ftruncate64")
-func libc_setgroups(size Size_t, list *Gid_t) int __asm__ ("setgroups")
-
-func Sleep(nsec int64) (errno int) {
-	tv := NsecToTimeval(nsec);
-	n, err := Select(0, nil, nil, nil, &tv);
-	return err;
-}
-
-func Setgroups(gids []int) (errno int) {
-	if len(gids) == 0 {
-		return libc_setgroups(0, nil);
-	}
-
-	a := make([]Gid_t, len(gids));
-	for i, v := range gids {
-		a[i] = Gid_t(v);
-	}
-	return libc_setgroups(Size_t(len(a)), &a[0]);
-}
diff -r 169c58c802a1 libgo/syscalls/sysfile_posix.go
--- a/libgo/syscalls/sysfile_posix.go	Wed Jan 12 15:04:36 2011 -0800
+++ b/libgo/syscalls/sysfile_posix.go	Wed Jan 12 18:09:18 2011 -0800
@@ -106,7 +106,7 @@ 
 }
 
 func Seek(fd int, offset int64, whence int) (off int64, errno int) {
-  r := libc_lseek64(fd, Offset_t(offset), whence);
+  r := libc_lseek(fd, Offset_t(offset), whence);
   if r == -1 { errno = GetErrno() }
   off = int64(r);
   return;
@@ -300,13 +300,13 @@ 
 }
 
 func Truncate(path string, length int64) (errno int) {
-  r := libc_truncate64(StringBytePtr(path), Offset_t(length));
+  r := libc_truncate(StringBytePtr(path), Offset_t(length));
   if r < 0 { errno = GetErrno() }
   return;
 }
 
 func Ftruncate(fd int, length int64) (errno int) {
-  r := libc_ftruncate64(fd, Offset_t(length));
+  r := libc_ftruncate(fd, Offset_t(length));
   if r < 0 { errno = GetErrno() }
   return;
 }
diff -r 169c58c802a1 libgo/syscalls/sysfile_regfile.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgo/syscalls/sysfile_regfile.go	Wed Jan 12 18:09:18 2011 -0800
@@ -0,0 +1,13 @@ 
+// sysfile_regfile.go -- For systems which do not use the large file interface.
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+func libc_pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pread")
+func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pwrite")
+func libc_lseek(int, Offset_t, int) Offset_t __asm__ ("lseek")
+func libc_truncate(path *byte, length Offset_t) int __asm__ ("truncate")
+func libc_ftruncate(fd int, length Offset_t) int __asm__ ("ftruncate")
diff -r 169c58c802a1 libgo/syscalls/sysfile_rtems.go
--- a/libgo/syscalls/sysfile_rtems.go	Wed Jan 12 15:04:36 2011 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@ 
-// sysfile_rtems.go -- RTEMS specific file handling.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Support for basic Unix file operations.  This file simply
-// translates from Go data types to Unix data types, and handles
-// errno.  FIXME: This could probably be done mechanically.
-
-package syscall
-
-const (
-	OS = "rtems"
-	// No support for async I/O in RTEMS.
-	O_ASYNC = 0
-)
-
-func libc_pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pread")
-func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pwrite")
-func libc_lseek64(int, Offset_t, int) Offset_t __asm__ ("lseek")
-func libc_truncate64(path *byte, length Offset_t) int __asm__ ("truncate")
-func libc_ftruncate64(fd int, length Offset_t) int __asm__ ("ftruncate")
-func libc_nanosleep(req *Timespec, rem *Timespec) int __asm__ ("nanosleep")
-
-func Sleep(nsec int64) (errno int) {
-	errno = 0
-	ts := NsecToTimespec(nsec)
-	r := libc_nanosleep(&ts, nil)
-	if r < 0 {
-		errno = GetErrno()
-	}
-	return
-}