summaryrefslogtreecommitdiff
path: root/libgo/go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go')
-rw-r--r--libgo/go/net/cgo_unix.go15
-rw-r--r--libgo/go/net/fd_select.go18
-rw-r--r--libgo/go/os/user/lookup_unix.go17
-rw-r--r--libgo/go/syscall/bpf_bsd.go169
-rw-r--r--libgo/go/syscall/errno.c25
-rw-r--r--libgo/go/syscall/errstr.go27
-rw-r--r--libgo/go/syscall/errstr_linux.go23
-rw-r--r--libgo/go/syscall/errstr_nor.go33
-rw-r--r--libgo/go/syscall/exec_stubs.go19
-rw-r--r--libgo/go/syscall/exec_unix.go454
-rw-r--r--libgo/go/syscall/exec_windows.go327
-rw-r--r--libgo/go/syscall/libcall_linux.go319
-rw-r--r--libgo/go/syscall/libcall_posix.go385
-rw-r--r--libgo/go/syscall/libcall_posix_largefile.go37
-rw-r--r--libgo/go/syscall/libcall_posix_regfile.go38
-rw-r--r--libgo/go/syscall/libcall_solaris_386.go9
-rw-r--r--libgo/go/syscall/libcall_support.go12
-rw-r--r--libgo/go/syscall/libcall_uname.go8
-rw-r--r--libgo/go/syscall/libcall_wait4.go21
-rw-r--r--libgo/go/syscall/libcall_waitpid.go21
-rw-r--r--libgo/go/syscall/lsf_linux.go78
-rw-r--r--libgo/go/syscall/mksyscall.awk233
-rw-r--r--libgo/go/syscall/netlink_linux.go229
-rw-r--r--libgo/go/syscall/route_bsd.go197
-rw-r--r--libgo/go/syscall/route_darwin.go77
-rw-r--r--libgo/go/syscall/route_freebsd.go77
-rw-r--r--libgo/go/syscall/route_openbsd.go35
-rw-r--r--libgo/go/syscall/sleep_rtems.go13
-rw-r--r--libgo/go/syscall/sleep_select.go13
-rw-r--r--libgo/go/syscall/sockcmsg_linux.go38
-rw-r--r--libgo/go/syscall/sockcmsg_unix.go115
-rw-r--r--libgo/go/syscall/socket.go423
-rw-r--r--libgo/go/syscall/socket_bsd.go78
-rw-r--r--libgo/go/syscall/socket_irix.go129
-rw-r--r--libgo/go/syscall/socket_linux.go183
-rw-r--r--libgo/go/syscall/socket_solaris.go80
-rw-r--r--libgo/go/syscall/str.go20
-rw-r--r--libgo/go/syscall/syscall.go35
-rw-r--r--libgo/go/syscall/syscall_linux_386.go15
-rw-r--r--libgo/go/syscall/syscall_linux_alpha.go47
-rw-r--r--libgo/go/syscall/syscall_linux_amd64.go15
-rw-r--r--libgo/go/syscall/syscall_stubs.go27
-rw-r--r--libgo/go/syscall/syscall_unix.go159
-rw-r--r--libgo/go/syscall/wait.c107
44 files changed, 4386 insertions, 14 deletions
diff --git a/libgo/go/net/cgo_unix.go b/libgo/go/net/cgo_unix.go
index b8090181293..d088eabc2b5 100644
--- a/libgo/go/net/cgo_unix.go
+++ b/libgo/go/net/cgo_unix.go
@@ -24,6 +24,17 @@ func libc_getaddrinfo(node *byte, service *byte, hints *syscall.Addrinfo, res **
func libc_freeaddrinfo(res *syscall.Addrinfo) __asm__ ("freeaddrinfo")
func libc_gai_strerror(errcode int) *byte __asm__ ("gai_strerror")
+// bytePtrToString takes a NUL-terminated array of bytes and convert
+// it to a Go string.
+func bytePtrToString(p *byte) string {
+ a := (*[10000]byte)(unsafe.Pointer(p))
+ i := 0
+ for a[i] != 0 {
+ i++
+ }
+ return string(a[:i])
+}
+
func cgoLookupHost(name string) (addrs []string, err os.Error, completed bool) {
ip, err, completed := cgoLookupIP(name)
for _, p := range ip {
@@ -99,13 +110,13 @@ func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err os.Error, comp
} else if gerrno == syscall.EAI_SYSTEM {
str = syscall.Errstr(syscall.GetErrno())
} else {
- str = syscall.BytePtrToString(libc_gai_strerror(gerrno))
+ str = bytePtrToString(libc_gai_strerror(gerrno))
}
return nil, "", &DNSError{Error: str, Name: name}, true
}
defer libc_freeaddrinfo(res)
if res != nil {
- cname = syscall.BytePtrToString((*byte)(unsafe.Pointer(res.Ai_canonname)))
+ cname = bytePtrToString((*byte)(unsafe.Pointer(res.Ai_canonname)))
if cname == "" {
cname = name
}
diff --git a/libgo/go/net/fd_select.go b/libgo/go/net/fd_select.go
index e9c68ab2ccc..21fd8010fa6 100644
--- a/libgo/go/net/fd_select.go
+++ b/libgo/go/net/fd_select.go
@@ -12,20 +12,20 @@ import (
)
type pollster struct {
- readFds, writeFds, repeatFds *syscall.FdSet_t
+ readFds, writeFds, repeatFds *syscall.FdSet
maxFd int
- readyReadFds, readyWriteFds *syscall.FdSet_t
+ readyReadFds, readyWriteFds *syscall.FdSet
nReady int
lastFd int
}
func newpollster() (p *pollster, err os.Error) {
p = new(pollster)
- p.readFds = new(syscall.FdSet_t)
- p.writeFds = new(syscall.FdSet_t)
- p.repeatFds = new(syscall.FdSet_t)
- p.readyReadFds = new(syscall.FdSet_t)
- p.readyWriteFds = new(syscall.FdSet_t)
+ p.readFds = new(syscall.FdSet)
+ p.writeFds = new(syscall.FdSet)
+ p.repeatFds = new(syscall.FdSet)
+ p.readyReadFds = new(syscall.FdSet)
+ p.readyWriteFds = new(syscall.FdSet)
p.maxFd = -1
p.nReady = 0
p.lastFd = 0
@@ -86,9 +86,9 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.E
}
var n, e int
- var tmpReadFds, tmpWriteFds syscall.FdSet_t
+ var tmpReadFds, tmpWriteFds syscall.FdSet
for {
- // Temporary syscall.FdSet_ts into which the values are copied
+ // Temporary syscall.FdSet's into which the values are copied
// because select mutates the values.
tmpReadFds = *p.readFds
tmpWriteFds = *p.writeFds
diff --git a/libgo/go/os/user/lookup_unix.go b/libgo/go/os/user/lookup_unix.go
index 0f04012c02f..18a9687c264 100644
--- a/libgo/go/os/user/lookup_unix.go
+++ b/libgo/go/os/user/lookup_unix.go
@@ -27,6 +27,17 @@ static int mygetpwuid_r(int uid, struct passwd *pwd,
func libc_getpwnam_r(name *byte, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int __asm__ ("getpwnam_r")
func libc_getpwuid_r(uid syscall.Uid_t, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int __asm__ ("getpwuid_r")
+// bytePtrToString takes a NUL-terminated array of bytes and convert
+// it to a Go string.
+func bytePtrToString(p *byte) string {
+ a := (*[10000]byte)(unsafe.Pointer(p))
+ i := 0
+ for a[i] != 0 {
+ i++
+ }
+ return string(a[:i])
+}
+
func init() {
implemented = true
}
@@ -78,9 +89,9 @@ func lookup(uid int, username string, lookupByName bool) (*User, os.Error) {
u := &User{
Uid: int(pwd.Pw_uid),
Gid: int(pwd.Pw_gid),
- Username: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))),
- Name: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))),
- HomeDir: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))),
+ Username: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))),
+ Name: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))),
+ HomeDir: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))),
}
// The pw_gecos field isn't quite standardized. Some docs
// say: "It is expected to be a comma separated list of
diff --git a/libgo/go/syscall/bpf_bsd.go b/libgo/go/syscall/bpf_bsd.go
new file mode 100644
index 00000000000..06a2953e7fe
--- /dev/null
+++ b/libgo/go/syscall/bpf_bsd.go
@@ -0,0 +1,169 @@
+// 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.
+
+// +build darwin freebsd openbsd
+
+// Berkeley packet filter for BSD variants
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+func BpfStmt(code, k int) *BpfInsn {
+ return &BpfInsn{Code: uint16(code), K: uint32(k)}
+}
+
+func BpfJump(code, k, jt, jf int) *BpfInsn {
+ return &BpfInsn{Code: uint16(code), Jt: uint8(jt), Jf: uint8(jf), K: uint32(k)}
+}
+
+func BpfBuflen(fd int) (int, int) {
+ var l int
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGBLEN, uintptr(unsafe.Pointer(&l)))
+ if e := int(ep); e != 0 {
+ return 0, e
+ }
+ return l, 0
+}
+
+func SetBpfBuflen(fd, l int) (int, int) {
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSBLEN, uintptr(unsafe.Pointer(&l)))
+ if e := int(ep); e != 0 {
+ return 0, e
+ }
+ return l, 0
+}
+
+func BpfDatalink(fd int) (int, int) {
+ var t int
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGDLT, uintptr(unsafe.Pointer(&t)))
+ if e := int(ep); e != 0 {
+ return 0, e
+ }
+ return t, 0
+}
+
+func SetBpfDatalink(fd, t int) (int, int) {
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSDLT, uintptr(unsafe.Pointer(&t)))
+ if e := int(ep); e != 0 {
+ return 0, e
+ }
+ return t, 0
+}
+
+func SetBpfPromisc(fd, m int) int {
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCPROMISC, uintptr(unsafe.Pointer(&m)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
+
+func FlushBpf(fd int) int {
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCFLUSH, 0)
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
+
+type ivalue struct {
+ name [IFNAMSIZ]byte
+ value int16
+}
+
+func BpfInterface(fd int, name string) (string, int) {
+ var iv ivalue
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGETIF, uintptr(unsafe.Pointer(&iv)))
+ if e := int(ep); e != 0 {
+ return "", e
+ }
+ return name, 0
+}
+
+func SetBpfInterface(fd int, name string) int {
+ var iv ivalue
+ copy(iv.name[:], []byte(name))
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETIF, uintptr(unsafe.Pointer(&iv)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
+
+func BpfTimeout(fd int) (*Timeval, int) {
+ var tv Timeval
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGRTIMEOUT, uintptr(unsafe.Pointer(&tv)))
+ if e := int(ep); e != 0 {
+ return nil, e
+ }
+ return &tv, 0
+}
+
+func SetBpfTimeout(fd int, tv *Timeval) int {
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSRTIMEOUT, uintptr(unsafe.Pointer(tv)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
+
+func BpfStats(fd int) (*BpfStat, int) {
+ var s BpfStat
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGSTATS, uintptr(unsafe.Pointer(&s)))
+ if e := int(ep); e != 0 {
+ return nil, e
+ }
+ return &s, 0
+}
+
+func SetBpfImmediate(fd, m int) int {
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCIMMEDIATE, uintptr(unsafe.Pointer(&m)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
+
+func SetBpf(fd int, i []BpfInsn) int {
+ var p BpfProgram
+ p.Len = uint32(len(i))
+ p.Insns = (*BpfInsn)(unsafe.Pointer(&i[0]))
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETF, uintptr(unsafe.Pointer(&p)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
+
+func CheckBpfVersion(fd int) int {
+ var v BpfVersion
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCVERSION, uintptr(unsafe.Pointer(&v)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ if v.Major != BPF_MAJOR_VERSION || v.Minor != BPF_MINOR_VERSION {
+ return EINVAL
+ }
+ return 0
+}
+
+func BpfHeadercmpl(fd int) (int, int) {
+ var f int
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGHDRCMPLT, uintptr(unsafe.Pointer(&f)))
+ if e := int(ep); e != 0 {
+ return 0, e
+ }
+ return f, 0
+}
+
+func SetBpfHeadercmpl(fd, f int) int {
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSHDRCMPLT, uintptr(unsafe.Pointer(&f)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
diff --git a/libgo/go/syscall/errno.c b/libgo/go/syscall/errno.c
new file mode 100644
index 00000000000..854b5aaec28
--- /dev/null
+++ b/libgo/go/syscall/errno.c
@@ -0,0 +1,25 @@
+/* errno.c -- functions for getting and setting errno
+
+ 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. */
+
+#include <errno.h>
+
+/* errno is typically a macro. These functions set
+ and get errno specific to the libc being used. */
+
+int GetErrno() asm ("libgo_syscall.syscall.GetErrno");
+void SetErrno(int) asm ("libgo_syscall.syscall.SetErrno");
+
+int
+GetErrno()
+{
+ return errno;
+}
+
+void
+SetErrno(int value)
+{
+ errno = value;
+}
diff --git a/libgo/go/syscall/errstr.go b/libgo/go/syscall/errstr.go
new file mode 100644
index 00000000000..d9f3fe82eb4
--- /dev/null
+++ b/libgo/go/syscall/errstr.go
@@ -0,0 +1,27 @@
+// errstr.go -- Error strings.
+
+// Copyright 2009 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
+
+//sysnb strerror_r(errnum int, buf []byte) (errno int)
+//strerror_r(errnum int, buf *byte, buflen Size_t) int
+
+func Errstr(errnum int) string {
+ for len := 128; ; len *= 2 {
+ b := make([]byte, len)
+ err := strerror_r(errnum, b)
+ if err == 0 {
+ i := 0
+ for b[i] != 0 {
+ i++
+ }
+ return string(b[:i])
+ }
+ if err != ERANGE {
+ return "Errstr failure"
+ }
+ }
+}
diff --git a/libgo/go/syscall/errstr_linux.go b/libgo/go/syscall/errstr_linux.go
new file mode 100644
index 00000000000..00fca80fc14
--- /dev/null
+++ b/libgo/go/syscall/errstr_linux.go
@@ -0,0 +1,23 @@
+// errstr_rtems.go -- RTEMS specific error strings.
+
+// 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
+
+import "unsafe"
+
+//sysnb strerror_r(errnum int, b []byte) (errstr *byte)
+//strerror_r(errnum int, b *byte, len Size_t) *byte
+
+func Errstr(errnum int) string {
+ a := make([]byte, 128)
+ p := strerror_r(errnum, a)
+ b := (*[1000]byte)(unsafe.Pointer(p))
+ i := 0
+ for b[i] != 0 {
+ i++
+ }
+ return string(b[:i])
+}
diff --git a/libgo/go/syscall/errstr_nor.go b/libgo/go/syscall/errstr_nor.go
new file mode 100644
index 00000000000..b331d0eb965
--- /dev/null
+++ b/libgo/go/syscall/errstr_nor.go
@@ -0,0 +1,33 @@
+// errstr.go -- Error strings when there is no strerror_r.
+
+// 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
+
+import (
+ "sync"
+ "unsafe"
+)
+
+//sysnb strerror(errnum int) *byte
+//strerror(errnum int) *byte
+
+var errstr_lock sync.Mutex
+
+func Errstr(errno int) string {
+ errstr_lock.Lock()
+
+ bp := libc_strerror(errno)
+ b := (*[1000]byte)(unsafe.Pointer(bp))
+ i := 0
+ for b[i] != 0 {
+ i++
+ }
+ s := string(b[:i])
+
+ errstr_lock.Unlock()
+
+ return s
+}
diff --git a/libgo/go/syscall/exec_stubs.go b/libgo/go/syscall/exec_stubs.go
new file mode 100644
index 00000000000..ce5dabe1e3b
--- /dev/null
+++ b/libgo/go/syscall/exec_stubs.go
@@ -0,0 +1,19 @@
+// 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.
+
+// Stubs for fork, exec and wait.
+
+package syscall
+
+func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
+ return -1, ENOSYS;
+}
+
+func Exec(argv0 string, argv []string, envv []string) (err int) {
+ return ENOSYS;
+}
+
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
+ return -1, ENOSYS;
+}
diff --git a/libgo/go/syscall/exec_unix.go b/libgo/go/syscall/exec_unix.go
new file mode 100644
index 00000000000..765f4d12fd5
--- /dev/null
+++ b/libgo/go/syscall/exec_unix.go
@@ -0,0 +1,454 @@
+// Copyright 2009 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.
+
+// +build darwin freebsd linux openbsd
+
+// Fork, exec, wait, etc.
+
+package syscall
+
+import (
+ "sync"
+ "unsafe"
+)
+
+//sysnb raw_fork() (pid Pid_t, errno int)
+//fork() Pid_t
+
+//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (errno int)
+//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long
+
+//sysnb raw_setsid() (errno int)
+//setsid() Pid_t
+
+//sysnb raw_chroot(path *byte) (errno int)
+//chroot(path *byte) int
+
+//sysnb raw_chdir(path *byte) (errno int)
+//chdir(path *byte) int
+
+//sysnb raw_fcntl(fd int, cmd int, arg int) (val int, errno int)
+//fcntl(fd int, cmd int, arg int) int
+
+//sysnb raw_close(fd int) (errno int)
+//close(fd int) int
+
+//sysnb raw_ioctl(fd int, cmd int, val int) (rval int, errno int)
+//ioctl(fd int, cmd int, val int) int
+
+//sysnb raw_execve(argv0 *byte, argv **byte, envv **byte) (errno int)
+//execve(argv0 *byte, argv **byte, envv **byte) int
+
+//sysnb raw_read(fd int, p *byte, np int) (n int, errno int)
+//read(fd int, buf *byte, count Size_t) Ssize_t
+
+//sysnb raw_write(fd int, buf *byte, count int) int
+//write(fd int, buf *byte, count Size_t) Ssize_t
+
+//sysnb raw_exit(status int)
+//_exit(status int)
+
+// Lock synchronizing creation of new file descriptors with fork.
+//
+// We want the child in a fork/exec sequence to inherit only the
+// file descriptors we intend. To do that, we mark all file
+// descriptors close-on-exec and then, in the child, explicitly
+// unmark the ones we want the exec'ed program to keep.
+// Unix doesn't make this easy: there is, in general, no way to
+// allocate a new file descriptor close-on-exec. Instead you
+// have to allocate the descriptor and then mark it close-on-exec.
+// If a fork happens between those two events, the child's exec
+// will inherit an unwanted file descriptor.
+//
+// This lock solves that race: the create new fd/mark close-on-exec
+// operation is done holding ForkLock for reading, and the fork itself
+// is done holding ForkLock for writing. At least, that's the idea.
+// There are some complications.
+//
+// Some system calls that create new file descriptors can block
+// for arbitrarily long times: open on a hung NFS server or named
+// pipe, accept on a socket, and so on. We can't reasonably grab
+// the lock across those operations.
+//
+// It is worse to inherit some file descriptors than others.
+// If a non-malicious child accidentally inherits an open ordinary file,
+// that's not a big deal. On the other hand, if a long-lived child
+// accidentally inherits the write end of a pipe, then the reader
+// of that pipe will not see EOF until that child exits, potentially
+// causing the parent program to hang. This is a common problem
+// in threaded C programs that use popen.
+//
+// Luckily, the file descriptors that are most important not to
+// inherit are not the ones that can take an arbitrarily long time
+// to create: pipe returns instantly, and the net package uses
+// non-blocking I/O to accept on a listening socket.
+// The rules for which file descriptor-creating operations use the
+// ForkLock are as follows:
+//
+// 1) Pipe. Does not block. Use the ForkLock.
+// 2) Socket. Does not block. Use the ForkLock.
+// 3) Accept. If using non-blocking mode, use the ForkLock.
+// Otherwise, live with the race.
+// 4) Open. Can block. Use O_CLOEXEC if available (Linux).
+// Otherwise, live with the race.
+// 5) Dup. Does not block. Use the ForkLock.
+// On Linux, could use fcntl F_DUPFD_CLOEXEC
+// instead of the ForkLock, but only for dup(fd, -1).
+
+var ForkLock sync.RWMutex
+
+// Convert array of string to array
+// of NUL-terminated byte pointer.
+func StringSlicePtr(ss []string) []*byte {
+ bb := make([]*byte, len(ss)+1)
+ for i := 0; i < len(ss); i++ {
+ bb[i] = StringBytePtr(ss[i])
+ }
+ bb[len(ss)] = nil
+ return bb
+}
+
+func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
+
+func SetNonblock(fd int, nonblocking bool) (errno int) {
+ flag, err := fcntl(fd, F_GETFL, 0)
+ if err != 0 {
+ return err
+ }
+ if nonblocking {
+ flag |= O_NONBLOCK
+ } else {
+ flag &= ^O_NONBLOCK
+ }
+ _, err = fcntl(fd, F_SETFL, flag)
+ return err
+}
+
+// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
+// If a dup or exec fails, write the errno int to pipe.
+// (Pipe is close-on-exec so if exec succeeds, it will be closed.)
+// In the child, this function must not acquire any locks, because
+// they might have been locked at the time of the fork. This means
+// no rescheduling, no malloc calls, and no new stack segments.
+// The calls to RawSyscall are okay because they are assembly
+// functions that do not grow the stack.
+func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err int) {
+ // Declare all variables at top in case any
+ // declarations require heap allocation (e.g., err1).
+ var r1 Pid_t
+ var err1 int
+ var nextfd int
+ var i int
+
+ // guard against side effects of shuffling fds below.
+ fd := append([]int(nil), attr.Files...)
+
+ // About to call fork.
+ // No more allocation or calls of non-assembly functions.
+ r1, err1 = raw_fork()
+ if err1 != 0 {
+ return 0, int(err1)
+ }
+
+ if r1 != 0 {
+ // parent; return PID
+ return int(r1), 0
+ }
+
+ // Fork succeeded, now in child.
+
+ // Enable tracing if requested.
+ if sys.Ptrace {
+ err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil)
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // Session ID
+ if sys.Setsid {
+ err1 = raw_setsid()
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // Set process group
+ if sys.Setpgid {
+ err1 = Setpgid(0, 0)
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // Chroot
+ if chroot != nil {
+ err1 = raw_chroot(chroot)
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // User and groups
+ if cred := sys.Credential; cred != nil {
+ ngroups := len(cred.Groups)
+ if ngroups == 0 {
+ err1 = setgroups(0, nil)
+ } else {
+ groups := make([]Gid_t, ngroups)
+ for i, v := range cred.Groups {
+ groups[i] = Gid_t(v)
+ }
+ err1 = setgroups(ngroups, &groups[0])
+ }
+ if err1 != 0 {
+ goto childerror
+ }
+ err1 = Setgid(int(cred.Gid))
+ if err1 != 0 {
+ goto childerror
+ }
+ err1 = Setuid(int(cred.Uid))
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // Chdir
+ if dir != nil {
+ err1 = raw_chdir(dir)
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // Pass 1: look for fd[i] < i and move those up above len(fd)
+ // so that pass 2 won't stomp on an fd it needs later.
+ nextfd = int(len(fd))
+ if pipe < nextfd {
+ _, err1 = Dup2(pipe, nextfd)
+ if err1 != 0 {
+ goto childerror
+ }
+ raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
+ pipe = nextfd
+ nextfd++
+ }
+ for i = 0; i < len(fd); i++ {
+ if fd[i] >= 0 && fd[i] < int(i) {
+ _, err1 = Dup2(fd[i], nextfd)
+ if err1 != 0 {
+ goto childerror
+ }
+ raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
+ fd[i] = nextfd
+ nextfd++
+ if nextfd == pipe { // don't stomp on pipe
+ nextfd++
+ }
+ }
+ }
+
+ // Pass 2: dup fd[i] down onto i.
+ for i = 0; i < len(fd); i++ {
+ if fd[i] == -1 {
+ raw_close(i)
+ continue
+ }
+ if fd[i] == int(i) {
+ // Dup2(i, i) won't clear close-on-exec flag on Linux,
+ // probably not elsewhere either.
+ _, err1 = raw_fcntl(fd[i], F_SETFD, 0)
+ if err1 != 0 {
+ goto childerror
+ }
+ continue
+ }
+ // The new fd is created NOT close-on-exec,
+ // which is exactly what we want.
+ _, err1 = Dup2(fd[i], i)
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // By convention, we don't close-on-exec the fds we are
+ // started with, so if len(fd) < 3, close 0, 1, 2 as needed.
+ // Programs that know they inherit fds >= 3 will need
+ // to set them close-on-exec.
+ for i = len(fd); i < 3; i++ {
+ raw_close(i)
+ }
+
+ // Detach fd 0 from tty
+ if sys.Noctty {
+ _, err1 = raw_ioctl(0, TIOCNOTTY, 0)
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // Make fd 0 the tty
+ if sys.Setctty {
+ _, err1 = raw_ioctl(0, TIOCSCTTY, 0)
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // Time to exec.
+ err1 = raw_execve(argv0, &argv[0], &envv[0])
+
+childerror:
+ // send error code on pipe
+ raw_write(pipe, (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
+ for {
+ raw_exit(253)
+ }
+
+ // Calling panic is not actually safe,
+ // but the for loop above won't break
+ // and this shuts up the compiler.
+ panic("unreached")
+}
+
+// Credential holds user and group identities to be assumed
+// by a child process started by StartProcess.
+type Credential struct {
+ Uid uint32 // User ID.
+ Gid uint32 // Group ID.
+ Groups []uint32 // Supplementary group IDs.
+}
+
+// ProcAttr holds attributes that will be applied to a new process started
+// by StartProcess.
+type ProcAttr struct {
+ Dir string // Current working directory.
+ Env []string // Environment.
+ Files []int // File descriptors.
+ Sys *SysProcAttr
+}
+
+type SysProcAttr struct {
+ Chroot string // Chroot.
+ Credential *Credential // Credential.
+ Ptrace bool // Enable tracing.
+ Setsid bool // Create session.
+ Setpgid bool // Set process group ID to new pid (SYSV setpgrp)
+ Setctty bool // Set controlling terminal to fd 0
+ Noctty bool // Detach fd 0 from controlling terminal
+}
+
+var zeroProcAttr ProcAttr
+var zeroSysProcAttr SysProcAttr
+
+func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
+ var p [2]int
+ var n int
+ var err1 uintptr
+ var wstatus WaitStatus
+
+ if attr == nil {
+ attr = &zeroProcAttr
+ }
+ sys := attr.Sys
+ if sys == nil {
+ sys = &zeroSysProcAttr
+ }
+
+ p[0] = -1
+ p[1] = -1
+
+ // Convert args to C form.
+ argv0p := StringBytePtr(argv0)
+ argvp := StringSlicePtr(argv)
+ envvp := StringSlicePtr(attr.Env)
+
+ if OS == "freebsd" && len(argv[0]) > len(argv0) {
+ argvp[0] = argv0p
+ }
+
+ var chroot *byte
+ if sys.Chroot != "" {
+ chroot = StringBytePtr(sys.Chroot)
+ }
+ var dir *byte
+ if attr.Dir != "" {
+ dir = StringBytePtr(attr.Dir)
+ }
+
+ // Acquire the fork lock so that no other threads
+ // create new fds that are not yet close-on-exec
+ // before we fork.
+ ForkLock.Lock()
+
+ // Allocate child status pipe close on exec.
+ if err = Pipe(p[0:]); err != 0 {
+ goto error
+ }
+ if _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != 0 {
+ goto error
+ }
+ if _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC); err != 0 {
+ goto error
+ }
+
+ // Kick off child.
+ pid, err = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])
+ if err != 0 {
+ goto error
+ }
+ ForkLock.Unlock()
+
+ // Read child error status from pipe.
+ Close(p[1])
+ n, err = raw_read(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
+ Close(p[0])
+ if err != 0 || n != 0 {
+ if n == int(unsafe.Sizeof(err1)) {
+ err = int(err1)
+ }
+ if err == 0 {
+ err = EPIPE
+ }
+
+ // Child failed; wait for it to exit, to make sure
+ // the zombies don't accumulate.
+ _, err1 := Wait4(pid, &wstatus, 0, nil)
+ for err1 == EINTR {
+ _, err1 = Wait4(pid, &wstatus, 0, nil)
+ }
+ return 0, err
+ }
+
+ // Read got EOF, so pipe closed on exec, so exec succeeded.
+ return pid, 0
+
+error:
+ if p[0] >= 0 {
+ Close(p[0])
+ Close(p[1])
+ }
+ ForkLock.Unlock()
+ return 0, err
+}
+
+// Combination of fork and exec, careful to be thread safe.
+func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
+ return forkExec(argv0, argv, attr)
+}
+
+// StartProcess wraps ForkExec for package os.
+func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err int) {
+ pid, err = forkExec(argv0, argv, attr)
+ return pid, 0, err
+}
+
+// Ordinary exec.
+func Exec(argv0 string, argv []string, envv []string) (err int) {
+ err1 := raw_execve(StringBytePtr(argv0),
+ &StringSlicePtr(argv)[0],
+ &StringSlicePtr(envv)[0])
+ return int(err1)
+}
diff --git a/libgo/go/syscall/exec_windows.go b/libgo/go/syscall/exec_windows.go
new file mode 100644
index 00000000000..e8b540ad160
--- /dev/null
+++ b/libgo/go/syscall/exec_windows.go
@@ -0,0 +1,327 @@
+// Copyright 2009 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.
+
+// Fork, exec, wait, etc.
+
+package syscall
+
+import (
+ "sync"
+ "unsafe"
+ "utf16"
+)
+
+var ForkLock sync.RWMutex
+
+// EscapeArg rewrites command line argument s as prescribed
+// in http://msdn.microsoft.com/en-us/library/ms880421.
+// This function returns "" (2 double quotes) if s is empty.
+// Alternatively, these transformations are done:
+// - every back slash (\) is doubled, but only if immediately
+// followed by double quote (");
+// - every double quote (") is escaped by back slash (\);
+// - finally, s is wrapped with double quotes (arg -> "arg"),
+// but only if there is space or tab inside s.
+func EscapeArg(s string) string {
+ if len(s) == 0 {
+ return "\"\""
+ }
+ n := len(s)
+ hasSpace := false
+ for i := 0; i < len(s); i++ {
+ switch s[i] {
+ case '"', '\\':
+ n++
+ case ' ', '\t':
+ hasSpace = true
+ }
+ }
+ if hasSpace {
+ n += 2
+ }
+ if n == len(s) {
+ return s
+ }
+
+ qs := make([]byte, n)
+ j := 0
+ if hasSpace {
+ qs[j] = '"'
+ j++
+ }
+ slashes := 0
+ for i := 0; i < len(s); i++ {
+ switch s[i] {
+ default:
+ slashes = 0
+ qs[j] = s[i]
+ case '\\':
+ slashes++
+ qs[j] = s[i]
+ case '"':
+ for ; slashes > 0; slashes-- {
+ qs[j] = '\\'
+ j++
+ }
+ qs[j] = '\\'
+ j++
+ qs[j] = s[i]
+ }
+ j++
+ }
+ if hasSpace {
+ for ; slashes > 0; slashes-- {
+ qs[j] = '\\'
+ j++
+ }
+ qs[j] = '"'
+ j++
+ }
+ return string(qs[:j])
+}
+
+// makeCmdLine builds a command line out of args by escaping "special"
+// characters and joining the arguments with spaces.
+func makeCmdLine(args []string) string {
+ var s string
+ for _, v := range args {
+ if s != "" {
+ s += " "
+ }
+ s += EscapeArg(v)
+ }
+ return s
+}
+
+// createEnvBlock converts an array of environment strings into
+// the representation required by CreateProcess: a sequence of NUL
+// terminated strings followed by a nil.
+// Last bytes are two UCS-2 NULs, or four NUL bytes.
+func createEnvBlock(envv []string) *uint16 {
+ if len(envv) == 0 {
+ return &utf16.Encode([]int("\x00\x00"))[0]
+ }
+ length := 0
+ for _, s := range envv {
+ length += len(s) + 1
+ }
+ length += 1
+
+ b := make([]byte, length)
+ i := 0
+ for _, s := range envv {
+ l := len(s)
+ copy(b[i:i+l], []byte(s))
+ copy(b[i+l:i+l+1], []byte{0})
+ i = i + l + 1
+ }
+ copy(b[i:i+1], []byte{0})
+
+ return &utf16.Encode([]int(string(b)))[0]
+}
+
+func CloseOnExec(fd Handle) {
+ SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
+}
+
+func SetNonblock(fd Handle, nonblocking bool) (errno int) {
+ return 0
+}
+
+// getFullPath retrieves the full path of the specified file.
+// Just a wrapper for Windows GetFullPathName api.
+func getFullPath(name string) (path string, err int) {
+ p := StringToUTF16Ptr(name)
+ buf := make([]uint16, 100)
+ n, err := GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
+ if err != 0 {
+ return "", err
+ }
+ if n > uint32(len(buf)) {
+ // Windows is asking for bigger buffer.
+ buf = make([]uint16, n)
+ n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
+ if err != 0 {
+ return "", err
+ }
+ if n > uint32(len(buf)) {
+ return "", EINVAL
+ }
+ }
+ return UTF16ToString(buf[:n]), 0
+}
+
+func isSlash(c uint8) bool {
+ return c == '\\' || c == '/'
+}
+
+func normalizeDir(dir string) (name string, err int) {
+ ndir, err := getFullPath(dir)
+ if err != 0 {
+ return "", err
+ }
+ if len(ndir) > 2 && isSlash(ndir[0]) && isSlash(ndir[1]) {
+ // dir cannot have \\server\share\path form
+ return "", EINVAL
+ }
+ return ndir, 0
+}
+
+func volToUpper(ch int) int {
+ if 'a' <= ch && ch <= 'z' {
+ ch += 'A' - 'a'
+ }
+ return ch
+}
+
+func joinExeDirAndFName(dir, p string) (name string, err int) {
+ if len(p) == 0 {
+ return "", EINVAL
+ }
+ if len(p) > 2 && isSlash(p[0]) && isSlash(p[1]) {
+ // \\server\share\path form
+ return p, 0
+ }
+ if len(p) > 1 && p[1] == ':' {
+ // has drive letter
+ if len(p) == 2 {
+ return "", EINVAL
+ }
+ if isSlash(p[2]) {
+ return p, 0
+ } else {
+ d, err := normalizeDir(dir)
+ if err != 0 {
+ return "", err
+ }
+ if volToUpper(int(p[0])) == volToUpper(int(d[0])) {
+ return getFullPath(d + "\\" + p[2:])
+ } else {
+ return getFullPath(p)
+ }
+ }
+ } else {
+ // no drive letter
+ d, err := normalizeDir(dir)
+ if err != 0 {
+ return "", err
+ }
+ if isSlash(p[0]) {
+ return getFullPath(d[:2] + p)
+ } else {
+ return getFullPath(d + "\\" + p)
+ }
+ }
+ // we shouldn't be here
+ return "", EINVAL
+}
+
+type ProcAttr struct {
+ Dir string
+ Env []string
+ Files []Handle
+ Sys *SysProcAttr
+}
+
+type SysProcAttr struct {
+ HideWindow bool
+ CmdLine string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
+}
+
+var zeroProcAttr ProcAttr
+var zeroSysProcAttr SysProcAttr
+
+func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err int) {
+ if len(argv0) == 0 {
+ return 0, 0, EWINDOWS
+ }
+ if attr == nil {
+ attr = &zeroProcAttr
+ }
+ sys := attr.Sys
+ if sys == nil {
+ sys = &zeroSysProcAttr
+ }
+
+ if len(attr.Files) > 3 {
+ return 0, 0, EWINDOWS
+ }
+
+ if len(attr.Dir) != 0 {
+ // StartProcess assumes that argv0 is relative to attr.Dir,
+ // because it implies Chdir(attr.Dir) before executing argv0.
+ // Windows CreateProcess assumes the opposite: it looks for
+ // argv0 relative to the current directory, and, only once the new
+ // process is started, it does Chdir(attr.Dir). We are adjusting
+ // for that difference here by making argv0 absolute.
+ var err int
+ argv0, err = joinExeDirAndFName(attr.Dir, argv0)
+ if err != 0 {
+ return 0, 0, err
+ }
+ }
+ argv0p := StringToUTF16Ptr(argv0)
+
+ var cmdline string
+ // Windows CreateProcess takes the command line as a single string:
+ // use attr.CmdLine if set, else build the command line by escaping
+ // and joining each argument with spaces
+ if sys.CmdLine != "" {
+ cmdline = sys.CmdLine
+ } else {
+ cmdline = makeCmdLine(argv)
+ }
+
+ var argvp *uint16
+ if len(cmdline) != 0 {
+ argvp = StringToUTF16Ptr(cmdline)
+ }
+
+ var dirp *uint16
+ if len(attr.Dir) != 0 {
+ dirp = StringToUTF16Ptr(attr.Dir)
+ }
+
+ // Acquire the fork lock so that no other threads
+ // create new fds that are not yet close-on-exec
+ // before we fork.
+ ForkLock.Lock()
+ defer ForkLock.Unlock()
+
+ p, _ := GetCurrentProcess()
+ fd := make([]Handle, len(attr.Files))
+ for i := range attr.Files {
+ if attr.Files[i] > 0 {
+ err := DuplicateHandle(p, Handle(attr.Files[i]), p, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
+ if err != 0 {
+ return 0, 0, err
+ }
+ defer CloseHandle(Handle(fd[i]))
+ }
+ }
+ si := new(StartupInfo)
+ si.Cb = uint32(unsafe.Sizeof(*si))
+ si.Flags = STARTF_USESTDHANDLES
+ if sys.HideWindow {
+ si.Flags |= STARTF_USESHOWWINDOW
+ si.ShowWindow = SW_HIDE
+ }
+ si.StdInput = fd[0]
+ si.StdOutput = fd[1]
+ si.StdErr = fd[2]
+
+ pi := new(ProcessInformation)
+
+ err = CreateProcess(argv0p, argvp, nil, nil, true, CREATE_UNICODE_ENVIRONMENT, createEnvBlock(attr.Env), dirp, si, pi)
+ if err != 0 {
+ return 0, 0, err
+ }
+ defer CloseHandle(Handle(pi.Thread))
+
+ return int(pi.ProcessId), int(pi.Process), 0
+}
+
+func Exec(argv0 string, argv []string, envv []string) (err int) {
+ return EWINDOWS
+}
diff --git a/libgo/go/syscall/libcall_linux.go b/libgo/go/syscall/libcall_linux.go
new file mode 100644
index 00000000000..d3e1d3a90c5
--- /dev/null
+++ b/libgo/go/syscall/libcall_linux.go
@@ -0,0 +1,319 @@
+// Copyright 2009 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.
+
+// GNU/Linux library calls.
+
+package syscall
+
+import "unsafe"
+
+//sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, errno int)
+//openat(dirfd int, path *byte, flags int, mode Mode_t) int
+
+//sys futimesat(dirfd int, path *byte, times *[2]Timeval) (errno int)
+//futimesat(dirfd int, path *byte, times *[2]Timeval) int
+func Futimesat(dirfd int, path string, tv []Timeval) (errno int) {
+ if len(tv) != 2 {
+ return EINVAL
+ }
+ return futimesat(dirfd, StringBytePtr(path), (*[2]Timeval)(unsafe.Pointer(&tv[0])))
+}
+
+func Futimes(fd int, tv []Timeval) (errno int) {
+ // Believe it or not, this is the best we can do on Linux
+ // (and is what glibc does).
+ return Utimes("/proc/self/fd/"+itoa(fd), tv)
+}
+
+//sys ptrace(request int, pid int, addr uintptr, data uintptr) (errno int)
+//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long
+
+func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, errno int) {
+ // The peek requests are machine-size oriented, so we wrap it
+ // to retrieve arbitrary-length data.
+
+ // The ptrace syscall differs from glibc's ptrace.
+ // Peeks returns the word in *data, not as the return value.
+
+ var buf [sizeofPtr]byte
+
+ // Leading edge. PEEKTEXT/PEEKDATA don't require aligned
+ // access (PEEKUSER warns that it might), but if we don't
+ // align our reads, we might straddle an unmapped page
+ // boundary and not get the bytes leading up to the page
+ // boundary.
+ n := 0
+ if addr%sizeofPtr != 0 {
+ errno = ptrace(req, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
+ if errno != 0 {
+ return 0, errno
+ }
+ n += copy(out, buf[addr%sizeofPtr:])
+ out = out[n:]
+ }
+
+ // Remainder.
+ for len(out) > 0 {
+ // We use an internal buffer to gaurantee alignment.
+ // It's not documented if this is necessary, but we're paranoid.
+ errno = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
+ if errno != 0 {
+ return n, errno
+ }
+ copied := copy(out, buf[0:])
+ n += copied
+ out = out[copied:]
+ }
+
+ return n, 0
+}
+
+func PtracePeekText(pid int, addr uintptr, out []byte) (count int, errno int) {
+ return ptracePeek(PTRACE_PEEKTEXT, pid, addr, out)
+}
+
+func PtracePeekData(pid int, addr uintptr, out []byte) (count int, errno int) {
+ return ptracePeek(PTRACE_PEEKDATA, pid, addr, out)
+}
+
+func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, errno int) {
+ // As for ptracePeek, we need to align our accesses to deal
+ // with the possibility of straddling an invalid page.
+
+ // Leading edge.
+ n := 0
+ if addr%sizeofPtr != 0 {
+ var buf [sizeofPtr]byte
+ errno = ptrace(peekReq, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
+ if errno != 0 {
+ return 0, errno
+ }
+ n += copy(buf[addr%sizeofPtr:], data)
+ word := *((*uintptr)(unsafe.Pointer(&buf[0])))
+ errno = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word)
+ if errno != 0 {
+ return 0, errno
+ }
+ data = data[n:]
+ }
+
+ // Interior.
+ for len(data) > int(sizeofPtr) {
+ word := *((*uintptr)(unsafe.Pointer(&data[0])))
+ errno = ptrace(pokeReq, pid, addr+uintptr(n), word)
+ if errno != 0 {
+ return n, errno
+ }
+ n += int(sizeofPtr)
+ data = data[sizeofPtr:]
+ }
+
+ // Trailing edge.
+ if len(data) > 0 {
+ var buf [sizeofPtr]byte
+ errno = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
+ if errno != 0 {
+ return n, errno
+ }
+ copy(buf[0:], data)
+ word := *((*uintptr)(unsafe.Pointer(&buf[0])))
+ errno = ptrace(pokeReq, pid, addr+uintptr(n), word)
+ if errno != 0 {
+ return n, errno
+ }
+ n += len(data)
+ }
+
+ return n, 0
+}
+
+func PtracePokeText(pid int, addr uintptr, data []byte) (count int, errno int) {
+ return ptracePoke(PTRACE_POKETEXT, PTRACE_PEEKTEXT, pid, addr, data)
+}
+
+func PtracePokeData(pid int, addr uintptr, data []byte) (count int, errno int) {
+ return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data)
+}
+
+func PtraceGetRegs(pid int, regsout *PtraceRegs) (errno int) {
+ return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
+}
+
+func PtraceSetRegs(pid int, regs *PtraceRegs) (errno int) {
+ return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))
+}
+
+func PtraceSetOptions(pid int, options int) (errno int) {
+ return ptrace(PTRACE_SETOPTIONS, pid, 0, uintptr(options))
+}
+
+func PtraceGetEventMsg(pid int) (msg uint, errno int) {
+ var data _C_long
+ errno = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data)))
+ msg = uint(data)
+ return
+}
+
+func PtraceCont(pid int, signal int) (errno int) {
+ return ptrace(PTRACE_CONT, pid, 0, uintptr(signal))
+}
+
+func PtraceSingleStep(pid int) (errno int) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) }
+
+func PtraceAttach(pid int) (errno int) { return ptrace(PTRACE_ATTACH, pid, 0, 0) }
+
+func PtraceDetach(pid int) (errno int) { return ptrace(PTRACE_DETACH, pid, 0, 0) }
+
+// FIXME: mksysinfo needs to produce LINUX_REBOOT_MAGIC[12].
+
+// //sys reboot(magic1 uint, magic2 uint, cmd int, arg string) (errno int)
+// //reboot(magic1 uint, magic2 uint, cmd int, arg *byte) int
+// func Reboot(cmd int) (errno int) {
+// return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "")
+// }
+
+//sys Acct(path string) (errno int)
+//acct(path *byte) int
+
+// FIXME: mksysinfo Timex
+// //sys Adjtimex(buf *Timex) (state int, errno int)
+// //adjtimex(buf *Timex) int
+
+//sys Faccessat(dirfd int, path string, mode uint32, flags int) (errno int)
+//faccessat(dirfd int, pathname *byte, mode int, flags int) int
+
+//sys Fallocate(fd int, mode uint32, off int64, len int64) (errno int)
+//fallocate(fd int, mode int, offset Offset_t, len Offset_t) int
+
+//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (errno int)
+//fchmodat(dirfd int, pathname *byte, mode Mode_t, flags int) int
+
+//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (errno int)
+//fchownat(dirfd int, path *byte, owner Uid_t, group Gid_t, flags int) int
+
+// FIXME: mksysinfo statfs
+// //sys Fstatfs(fd int, buf *Statfs_t) (errno int)
+// //fstatfs(fd int, buf *Statfs_t) int
+
+//sys Ioperm(from int, num int, on int) (errno int)
+//ioperm(from _C_long, num _C_long, on int) int
+
+//sys Iopl(level int) (errno int)
+//iopl(level int) int
+
+// FIXME: mksysinfo linux_dirent
+// Or just abandon this function.
+// //sys Getdents(fd int, buf []byte) (n int, errno int)
+// //getdents64(fd int, buf *byte, count uint)
+
+//sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, errno int)
+//inotify_add_watch(fd int, pathname *byte, mask uint32) int
+
+//sysnb InotifyInit() (fd int, errno int)
+//inotify_init() int
+
+//sysnb InotifyInit1(flags int) (fd int, errno int)
+//inotify_init1(flags int) int
+
+//sysnb InotifyRmWatch(fd int, watchdesc uint32) (success int, errno int)
+//inotify_rm_watch(fd int, wd uint32) int
+
+//sys Klogctl(typ int, buf []byte) (n int, errno int)
+//klogctl(typ int, bufp *byte, len int) int
+
+//sys Mkdirat(dirfd int, path string, mode uint32) (errno int)
+//mkdirat(dirfd int, path *byte, mode Mode_t) int
+
+//sys Mknodat(dirfd int, path string, mode uint32, dev int) (errno int)
+//mknodat(dirfd int, path *byte, mode Mode_t, dev _dev_t) int
+
+//sys PivotRoot(newroot string, putold string) (errno int)
+//pivot_root(newroot *byte, putold *byte) int
+
+//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (errno int)
+//renameat(olddirfd int, oldpath *byte, newdirfd int, newpath *byte) int
+
+//sys sendfile(outfd int, infd int, offset *Offset_t, count int) (written int, errno int)
+//sendfile64(outfd int, infd int, offset *Offset_t, count Size_t) Ssize_t
+func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int) {
+ var soff Offset_t
+ var psoff *Offset_t
+ if offset != nil {
+ psoff = &soff
+ }
+ written, errno = sendfile(outfd, infd, psoff, count)
+ if offset != nil {
+ *offset = int64(soff)
+ }
+ return
+}
+
+//sys Setfsgid(gid int) (errno int)
+//setfsgid(gid Gid_t) int
+
+//sys Setfsuid(uid int) (errno int)
+//setfsuid(uid Uid_t) int
+
+//sysnb Setresgid(rgid int, egid int, sgid int) (errno int)
+//setresgid(rgid Gid_t, egid Gid_t, sgid Gid_t) int
+
+//sysnb Setresuid(ruid int, eguid int, suid int) (errno int)
+//setresuid(ruid Uid_t, euid Uid_t, suid Uid_t) int
+
+//sys splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len int, flags int) (n int64, errno int)
+//splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len Size_t, flags uint) Ssize_t
+func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, errno int) {
+ var lroff _loff_t
+ var plroff *_loff_t
+ if (roff != nil) {
+ plroff = &lroff
+ }
+ var lwoff _loff_t
+ var plwoff *_loff_t
+ if (woff != nil) {
+ plwoff = &lwoff
+ }
+ n, errno = splice(rfd, plroff, wfd, plwoff, len, flags)
+ if (roff != nil) {
+ *roff = int64(lroff)
+ }
+ if (woff != nil) {
+ *woff = int64(lwoff)
+ }
+ return
+}
+
+// FIXME: mksysinfo statfs
+// //sys Statfs(path string, buf *Statfs_t) (errno int)
+// //statfs(path *byte, buf *Statfs_t) int
+
+//sys SyncFileRange(fd int, off int64, n int64, flags int) (errno int)
+//sync_file_range(fd int, off Offset_t, n Offset_t, flags uint) int
+
+// FIXME: mksysinfo Sysinfo_t
+// //sysnb Sysinfo(info *Sysinfo_t) (errno int)
+// //sysinfo(info *Sysinfo_t) int
+
+//sys Tee(rfd int, wfd int, len int, flags int) (n int64, errno int)
+//tee(rfd int, wfd int, len Size_t, flags uint) Ssize_t
+
+//sysnb Tgkill(tgid int, tid int, sig int) (errno int)
+//tgkill(tgid int, tid int, sig int) int
+
+//sys unlinkat(dirfd int, path string, flags int) (errno int)
+//unlinkat(dirfd int, path *byte, flags int) int
+
+func Unlinkat(dirfd int, path string) (errno int) {
+ return unlinkat(dirfd, path, 0)
+}
+
+//sys Unmount(target string, flags int) (errno int) = SYS_UMOUNT2
+//umount2(target *byte, flags int) int
+
+//sys Unshare(flags int) (errno int)
+//unshare(flags int) int
+
+// FIXME: mksysinfo Ustat_t
+// //sys Ustat(dev int, ubuf *Ustat_t) (errno int)
+// //ustat(dev _dev_t, ubuf *Ustat_t) int
diff --git a/libgo/go/syscall/libcall_posix.go b/libgo/go/syscall/libcall_posix.go
new file mode 100644
index 00000000000..ea7dfc89af7
--- /dev/null
+++ b/libgo/go/syscall/libcall_posix.go
@@ -0,0 +1,385 @@
+// 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.
+
+// POSIX library calls.
+// This file is compiled as ordinary Go code,
+// but it is also input to mksyscall,
+// which parses the //sys lines and generates library call stubs.
+// Note that sometimes we use a lowercase //sys name and
+// wrap it in our own nicer implementation.
+
+package syscall
+
+import "unsafe"
+
+/*
+ * Wrapped
+ */
+
+//sysnb pipe(p *[2]int) (errno int)
+//pipe(p *[2]int) int
+func Pipe(p []int) (errno int) {
+ if len(p) != 2 {
+ return EINVAL
+ }
+ var pp [2]int
+ errno = pipe(&pp)
+ p[0] = pp[0]
+ p[1] = pp[1]
+ return
+}
+
+//sys utimes(path string, times *[2]Timeval) (errno int)
+//utimes(path *byte, times *[2]Timeval) int
+func Utimes(path string, tv []Timeval) (errno int) {
+ if len(tv) != 2 {
+ return EINVAL
+ }
+ return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
+}
+
+//sys getcwd(buf *byte, size Size_t) (errno int)
+//getcwd(buf *byte, size Size_t) *byte
+
+const ImplementsGetwd = true
+
+func Getwd() (ret string, errno int) {
+ for len := Size_t(4096); ; len *= 2 {
+ b := make([]byte, len)
+ err := getcwd(&b[0], len)
+ if err == 0 {
+ i := 0;
+ for b[i] != 0 {
+ i++;
+ }
+ return string(b[0:i]), 0;
+ }
+ if err != ERANGE {
+ return "", err
+ }
+ }
+}
+
+//sysnb getgroups(size int, list *Gid_t) (nn int, errno int)
+//getgroups(size int, list *Gid_t) int
+
+func Getgroups() (gids []int, errno int) {
+ n, err := getgroups(0, nil)
+ if err != 0 {
+ return nil, errno
+ }
+ if n == 0 {
+ return nil, 0
+ }
+
+ // Sanity check group count. Max is 1<<16 on Linux.
+ if n < 0 || n > 1<<20 {
+ return nil, EINVAL
+ }
+
+ a := make([]Gid_t, n)
+ n, err = getgroups(n, &a[0])
+ if err != 0 {
+ return nil, errno
+ }
+ gids = make([]int, n)
+ for i, v := range a[0:n] {
+ gids[i] = int(v)
+ }
+ return
+}
+
+//sysnb setgroups(n int, list *Gid_t) (errno int)
+//setgroups(n Size_t, list *Gid_t) int
+
+func Setgroups(gids []int) (errno int) {
+ if len(gids) == 0 {
+ return setgroups(0, nil)
+ }
+
+ a := make([]Gid_t, len(gids))
+ for i, v := range gids {
+ a[i] = Gid_t(v)
+ }
+ return setgroups(len(a), &a[0])
+}
+
+type WaitStatus uint32
+
+// The WaitStatus methods are implemented in C, to pick up the macros
+// #defines in <sys/wait.h>.
+
+func (w WaitStatus) Exited() bool
+func (w WaitStatus) Signaled() bool
+func (w WaitStatus) Stopped() bool
+func (w WaitStatus) Continued() bool
+func (w WaitStatus) CoreDump() bool
+func (w WaitStatus) ExitStatus() int
+func (w WaitStatus) Signal() int
+func (w WaitStatus) StopSignal() int
+func (w WaitStatus) TrapCause() int
+
+//sys Mkfifo(path string, mode uint32) (errno int)
+//mkfifo(path *byte, mode Mode_t) int
+
+//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, errno int)
+//select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) int
+
+const nfdbits = unsafe.Sizeof(fds_bits_type) * 8
+
+type FdSet struct {
+ Bits [(FD_SETSIZE + nfdbits - 1) / nfdbits]fds_bits_type
+}
+
+func FDSet(fd int, set *FdSet) {
+ set.Bits[fd / nfdbits] |= (1 << (uint)(fd % nfdbits))
+}
+
+func FDClr(fd int, set *FdSet) {
+ set.Bits[fd / nfdbits] &^= (1 << (uint)(fd % nfdbits))
+}
+
+func FDIsSet(fd int, set *FdSet) bool {
+ if set.Bits[fd / nfdbits] & (1 << (uint)(fd % nfdbits)) != 0 {
+ return true
+ } else {
+ return false
+ }
+}
+
+func FDZero(set *FdSet) {
+ for i := range set.Bits {
+ set.Bits[i] = 0
+ }
+}
+
+//sys Access(path string, mode uint32) (errno int)
+//access(path *byte, mode int) int
+
+//sys Chdir(path string) (errno int)
+//chdir(path *byte) int
+
+//sys Chmod(path string, mode uint32) (errno int)
+//chmod(path *byte, mode Mode_t) int
+
+//sys Chown(path string, uid int, gid int) (errno int)
+//chown(path *byte, uid Uid_t, gid Gid_t) int
+
+//sys Chroot(path string) (errno int)
+//chroot(path *byte) int
+
+//sys Close(fd int) (errno int)
+//close(fd int) int
+
+//sys Creat(path string, mode uint32) (fd int, errno int)
+//creat(path *byte, mode Mode_t) int
+
+//sysnb Dup(oldfd int) (fd int, errno int)
+//dup(oldfd int) int
+
+//sysnb Dup2(oldfd int, newfd int) (fd int, errno int)
+//dup2(oldfd int, newfd int) int
+
+//sys Exit(code int)
+//exit(code int)
+
+//sys Fchdir(fd int) (errno int)
+//fchdir(fd int) int
+
+//sys Fchmod(fd int, mode uint32) (errno int)
+//fchmod(fd int, mode Mode_t) int
+
+//sys Fchown(fd int, uid int, gid int) (errno int)
+//fchown(fd int, uid Uid_t, gid Gid_t) int
+
+//sys fcntl(fd int, cmd int, arg int) (val int, errno int)
+//fcntl(fd int, cmd int, arg int) int
+
+//sys Fdatasync(fd int) (errno int)
+//fdatasync(fd int) int
+
+//sys Flock(fd int, how int) (errno int)
+//flock(fd int, how int) int
+
+//sys Fsync(fd int) (errno int)
+//fsync(fd int) int
+
+//sysnb Getegid() (egid int)
+//getegid() Gid_t
+
+//sysnb Geteuid() (euid int)
+//geteuid() Uid_t
+
+//sysnb Getgid() (gid int)
+//getgid() Gid_t
+
+//sysnb Getpagesize() (pagesize int)
+//getpagesize() int
+
+//sysnb Getpgid(pid int) (pgid int, errno int)
+//getpgid(pid Pid_t) Pid_t
+
+//sysnb Getpgrp() (pid int)
+//getpgrp() Pid_t
+
+//sysnb Getpid() (pid int)
+//getpid() Pid_t
+
+//sysnb Getppid() (ppid int)
+//getppid() Pid_t
+
+// FIXME: mksysinfo Rlimit
+// //sysnb Getrlimit(resource int, rlim *Rlimit) (errno int)
+// //getrlimit(resource int, rlim *Rlimit) int
+
+//sysnb Getrusage(who int, rusage *Rusage) (errno int)
+//getrusage(who int, rusage *Rusage) int
+
+//sysnb Gettid() (tid int)
+//gettid() Pid_t
+
+//sysnb gettimeofday(tv *Timeval, tz *byte) (errno int)
+//gettimeofday(tv *Timeval, tz *byte) int
+func Gettimeofday(tv *Timeval) (errno int) {
+ return gettimeofday(tv, nil)
+}
+
+//sysnb Getuid() (uid int)
+//getuid() Uid_t
+
+//sysnb Kill(pid int, sig int) (errno int)
+//kill(pid Pid_t, sig int) int
+
+//sys Lchown(path string, uid int, gid int) (errno int)
+//lchown(path *byte, uid Uid_t, gid Gid_t) int
+
+//sys Link(oldpath string, newpath string) (errno int)
+//link(oldpath *byte, newpath *byte) int
+
+//sys Mkdir(path string, mode uint32) (errno int)
+//mkdir(path *byte, mode Mode_t) int
+
+//sys Mknod(path string, mode uint32, dev int) (errno int)
+//mknod(path *byte, mode Mode_t, dev _dev_t) int
+
+//sys Mount(source string, target string, fstype string, flags int, data string) (errno int)
+//mount(source *byte, target *byte, fstype *byte, flags _C_long, data *byte) int
+
+//sys Nanosleep(time *Timespec, leftover *Timespec) (errno int)
+//nanosleep(time *Timespec, leftover *Timespec) int
+
+//sys Pause() (errno int)
+//pause() int
+
+//sys Read(fd int, p []byte) (n int, errno int)
+//read(fd int, buf *byte, count Size_t) Ssize_t
+
+//sys Readlink(path string, buf []byte) (n int, errno int)
+//readlink(path *byte, buf *byte, bufsiz Size_t) Ssize_t
+
+//sys Rename(oldpath string, newpath string) (errno int)
+//rename(oldpath *byte, newpath *byte) int
+
+//sys Rmdir(path string) (errno int)
+//rmdir(path *byte) int
+
+//sys Setdomainname(p []byte) (errno int)
+//setdomainname(name *byte, len Size_t) int
+
+//sys Sethostname(p []byte) (errno int)
+//sethostname(name *byte, len Size_t) int
+
+//sysnb Setgid(gid int) (errno int)
+//setgid(gid Gid_t) int
+
+//sysnb Setregid(rgid int, egid int) (errno int)
+//setregid(rgid Gid_t, egid Gid_t) int
+
+//sysnb Setpgid(pid int, pgid int) (errno int)
+//setpgid(pid Pid_t, pgid Pid_t) int
+
+//sysnb Setreuid(ruid int, euid int) (errno int)
+//setreuid(ruid Uid_t, euid Uid_t) int
+
+// FIXME: mksysinfo Rlimit
+// //sysnb Setrlimit(resource int, rlim *Rlimit) (errno int)
+// //setrlimit(resource int, rlim *Rlimit) int
+
+//sysnb Setsid() (pid int, errno int)
+//setsid() Pid_t
+
+//sysnb settimeofday(tv *Timeval, tz *byte) (errno int)
+//settimeofday(tv *Timeval, tz *byte) int
+
+func Settimeofday(tv *Timeval) (errno int) {
+ return settimeofday(tv, nil)
+}
+
+//sysnb Setuid(uid int) (errno int)
+//setuid(uid Uid_t) int
+
+//sys Symlink(oldpath string, newpath string) (errno int)
+//symlink(oldpath *byte, newpath *byte) int
+
+//sys Sync()
+//sync()
+
+// FIXME: mksysinfo Time_t
+// //sysnb Time(t *Time_t) (tt Time_t, errno int)
+// //time(t *Time_t) Time_t
+
+// FIXME: mksysinfo Tms
+// //sysnb Times(tms *Tms) (ticks uintptr, errno int)
+// //times(tms *Tms) _clock_t
+
+//sysnb Umask(mask int) (oldmask int)
+//umark(mask Mode_t) Mode_t
+
+//sys Unlink(path string) (errno int)
+//unlink(path *byte) int
+
+// FIXME: mksysinfo Utimbuf
+// //sys Utime(path string, buf *Utimbuf) (errno int)
+// //utime(path *byte, buf *Utimbuf) int
+
+//sys Write(fd int, p []byte) (n int, errno int)
+//write(fd int, buf *byte, count Size_t) Ssize_t
+
+//sys munmap(addr uintptr, length uintptr) (errno int)
+//munmap(addr *byte, length Size_t) int
+
+//sys Madvise(b []byte, advice int) (errno int)
+//madvise(addr *byte, len Size_t, advice int) int
+
+//sys Mprotect(b []byte, prot int) (errno int)
+//mprotect(addr *byte, len Size_t, prot int) int
+
+//sys Mlock(b []byte) (errno int)
+//mlock(addr *byte, len Size_t) int
+
+//sys Munlock(b []byte) (errno int)
+//munlock(addr *byte, len Size_t) int
+
+//sys Mlockall(flags int) (errno int)
+//mlockall(flags int) int
+
+//sys Munlockall() (errno int)
+//munlockall() int
+
+func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
+
+func NsecToTimespec(nsec int64) (ts Timespec) {
+ ts.Sec = Timespec_sec_t(nsec / 1e9)
+ ts.Nsec = Timespec_nsec_t(nsec % 1e9)
+ return
+}
+
+func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
+
+func NsecToTimeval(nsec int64) (tv Timeval) {
+ nsec += 999 // round up to microsecond
+ tv.Sec = Timeval_sec_t(nsec / 1e9)
+ tv.Usec = Timeval_usec_t(nsec % 1e9 / 1e3)
+ return
+}
diff --git a/libgo/go/syscall/libcall_posix_largefile.go b/libgo/go/syscall/libcall_posix_largefile.go
new file mode 100644
index 00000000000..acfafecc581
--- /dev/null
+++ b/libgo/go/syscall/libcall_posix_largefile.go
@@ -0,0 +1,37 @@
+// Copyright 2009 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.
+
+// POSIX library calls on systems which use the largefile interface.
+
+package syscall
+
+//sys Fstat(fd int, stat *Stat_t) (errno int)
+//fstat64(fd int, stat *Stat_t) int
+
+//sys Ftruncate(fd int, length int64) (errno int)
+//ftruncate64(fd int, length Offset_t) int
+
+//sys Lstat(path string, stat *Stat_t) (errno int)
+//lstat64(path *byte, stat *Stat_t) int
+
+//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, errno int)
+//mmap64(addr *byte, length Size_t, prot int, flags int, fd int, offset Offset_t) *byte
+
+//sys Open(path string, mode int, perm uint32) (fd int, errno int)
+//open64(path *byte, mode int, perm Mode_t) int
+
+//sys Pread(fd int, p []byte, offset int64) (n int, errno int)
+//pread64(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t
+
+//sys Pwrite(fd int, p []byte, offset int64) (n int, errno int)
+//pwrite64(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t
+
+//sys Seek(fd int, offset int64, whence int) (off int64, errno int)
+//lseek64(fd int, offset Offset_t, whence int) Offset_t
+
+//sys Stat(path string, stat *Stat_t) (errno int)
+//stat64(path *byte, stat *Stat_t) int
+
+//sys Truncate(path string, length int64) (errno int)
+//truncate64(path *byte, length Offset_t) int
diff --git a/libgo/go/syscall/libcall_posix_regfile.go b/libgo/go/syscall/libcall_posix_regfile.go
new file mode 100644
index 00000000000..b71da0ceb48
--- /dev/null
+++ b/libgo/go/syscall/libcall_posix_regfile.go
@@ -0,0 +1,38 @@
+// Copyright 2009 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.
+
+// POSIX library calls on systems which do not use the largefile
+// interface.
+
+package syscall
+
+//sys Fstat(fd int, stat *Stat_t) (errno int)
+//fstat(fd int, stat *Stat_t) int
+
+//sys Ftruncate(fd int, length int64) (errno int)
+//ftruncate(fd int, length Offset_t) int
+
+//sys Lstat(path string, stat *Stat_t) (errno int)
+//lstat(path *byte, stat *Stat_t) int
+
+//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, errno int)
+//mmap(addr *byte, length Size_t, prot int, flags int, fd int, offset Offset_t) *byte
+
+//sys Open(path string, mode int, perm uint32) (fd int, errno int)
+//open(path *byte, mode int, perm Mode_t) int
+
+//sys Pread(fd int, p []byte, offset int64) (n int, errno int)
+//pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t
+
+//sys Pwrite(fd int, p []byte, offset int64) (n int, errno int)
+//pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t
+
+//sys Seek(fd int, offset int64, whence int) (off int64, errno int)
+//lseek(fd int, offset Offset_t, whence int) Offset_t
+
+//sys Stat(path string, stat *Stat_t) (errno int)
+//stat(path *byte, stat *Stat_t) int
+
+//sys Truncate(path string, length int64) (errno int)
+//truncate(path *byte, length Offset_t) int
diff --git a/libgo/go/syscall/libcall_solaris_386.go b/libgo/go/syscall/libcall_solaris_386.go
new file mode 100644
index 00000000000..a008a221db2
--- /dev/null
+++ b/libgo/go/syscall/libcall_solaris_386.go
@@ -0,0 +1,9 @@
+// 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
+
+// 32-bit Solaris 2/x86 needs to use _nuname internally, cf. <sys/utsname.h>.
+//sysnb Uname(buf *Utsname) (errno int)
+//_nuname(buf *Utsname) int
diff --git a/libgo/go/syscall/libcall_support.go b/libgo/go/syscall/libcall_support.go
new file mode 100644
index 00000000000..daed8073caf
--- /dev/null
+++ b/libgo/go/syscall/libcall_support.go
@@ -0,0 +1,12 @@
+// 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.
+
+// Declarations for functions which are actually written in C.
+
+package syscall
+
+func entersyscall()
+func exitsyscall()
+func GetErrno() int
+func SetErrno(int)
diff --git a/libgo/go/syscall/libcall_uname.go b/libgo/go/syscall/libcall_uname.go
new file mode 100644
index 00000000000..e4c32b12d6a
--- /dev/null
+++ b/libgo/go/syscall/libcall_uname.go
@@ -0,0 +1,8 @@
+// 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
+
+//sysnb Uname(buf *Utsname) (errno int)
+//uname(buf *Utsname) int
diff --git a/libgo/go/syscall/libcall_wait4.go b/libgo/go/syscall/libcall_wait4.go
new file mode 100644
index 00000000000..7a63bc71e97
--- /dev/null
+++ b/libgo/go/syscall/libcall_wait4.go
@@ -0,0 +1,21 @@
+// Copyright 2009 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.
+
+// For systems with the wait4 library call.
+
+package syscall
+
+//sys wait4(pid Pid_t, status *int, options int, rusage *Rusage) (wpid Pid_t, errno int)
+//wait4(pid Pid_t, status *int, options int, rusage *Rusage) Pid_t
+
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
+ var status int
+ r, err := wait4(Pid_t(pid), &status, options, rusage)
+ wpid = int(r)
+ errno = err
+ if wstatus != nil {
+ *wstatus = WaitStatus(status)
+ }
+ return
+}
diff --git a/libgo/go/syscall/libcall_waitpid.go b/libgo/go/syscall/libcall_waitpid.go
new file mode 100644
index 00000000000..014446307e3
--- /dev/null
+++ b/libgo/go/syscall/libcall_waitpid.go
@@ -0,0 +1,21 @@
+// Copyright 2009 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.
+
+// For systems with the waitpid library call.
+
+package syscall
+
+//sys waitpid(pid Pid_t, status *int, options int) (wpid Pid_t, errno int)
+//waitpid(pid Pid_t, status *int, options int) Pid_t
+
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
+ var status int
+ r, err := waitpid(Pid_t(pid), &status, options)
+ wpid = int(r)
+ errno = err
+ if wstatus != nil {
+ *wstatus = WaitStatus(status)
+ }
+ return
+}
diff --git a/libgo/go/syscall/lsf_linux.go b/libgo/go/syscall/lsf_linux.go
new file mode 100644
index 00000000000..f2bd2b757f9
--- /dev/null
+++ b/libgo/go/syscall/lsf_linux.go
@@ -0,0 +1,78 @@
+// 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.
+
+// Linux socket filter
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+func LsfStmt(code, k int) *SockFilter {
+ return &SockFilter{Code: uint16(code), K: uint32(k)}
+}
+
+func LsfJump(code, k, jt, jf int) *SockFilter {
+ return &SockFilter{Code: uint16(code), Jt: uint8(jt), Jf: uint8(jf), K: uint32(k)}
+}
+
+func LsfSocket(ifindex, proto int) (int, int) {
+ var lsall SockaddrLinklayer
+ s, e := Socket(AF_PACKET, SOCK_RAW, proto)
+ if e != 0 {
+ return 0, e
+ }
+ p := (*[2]byte)(unsafe.Pointer(&lsall.Protocol))
+ p[0] = byte(proto >> 8)
+ p[1] = byte(proto)
+ lsall.Ifindex = ifindex
+ e = Bind(s, &lsall)
+ if e != 0 {
+ Close(s)
+ return 0, e
+ }
+ return s, 0
+}
+
+type iflags struct {
+ name [IFNAMSIZ]byte
+ flags uint16
+}
+
+func SetLsfPromisc(name string, m bool) int {
+ s, e := Socket(AF_INET, SOCK_DGRAM, 0)
+ if e != 0 {
+ return e
+ }
+ defer Close(s)
+ var ifl iflags
+ copy(ifl.name[:], []byte(name))
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(s), SIOCGIFFLAGS, uintptr(unsafe.Pointer(&ifl)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ if m {
+ ifl.flags |= uint16(IFF_PROMISC)
+ } else {
+ ifl.flags &= ^uint16(IFF_PROMISC)
+ }
+ _, _, ep = Syscall(SYS_IOCTL, uintptr(s), SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifl)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
+
+func AttachLsf(fd int, i []SockFilter) int {
+ var p SockFprog
+ p.Len = uint16(len(i))
+ p.Filter = (*SockFilter)(unsafe.Pointer(&i[0]))
+ return setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, uintptr(unsafe.Pointer(&p)), unsafe.Sizeof(p))
+}
+
+func DetachLsf(fd int) int {
+ var dummy int
+ return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, uintptr(unsafe.Pointer(&dummy)), unsafe.Sizeof(dummy))
+}
diff --git a/libgo/go/syscall/mksyscall.awk b/libgo/go/syscall/mksyscall.awk
new file mode 100644
index 00000000000..d19a8ba73fc
--- /dev/null
+++ b/libgo/go/syscall/mksyscall.awk
@@ -0,0 +1,233 @@
+# 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.
+
+# This AWK script reads a Go file with comments describing syscall
+# functions and the C routines they map to. It generates the Go code
+# which calls the C routines.
+
+# The syscall functins are marked by lines beginning with "//sys" and
+# read like func declarations if //sys is replaced by func, but:
+# * The parameter lists must give a name for each argument.
+# This includes return parameters.
+# * The parameter lists must give a type for each argument:
+# the (x, y, z int) shorthand is not allowed.
+# * If the return parameter is an error number, it must be named errno.
+
+# A line beginning with //sysnb is like //sys, except that the
+# goroutine will not be suspended during the execution of the library
+# call. This must only be used for library calls which can never
+# block, as otherwise the library call could cause all goroutines to
+# hang.
+
+# After the //sys or //sysnb line comes a second line which describes
+# the C function. The name must be the name of the function in the C
+# library, and may be the same as the Go function. The limitations on
+# the argument list are the same as for the //sys line, but there must
+# be at most one result parameter, and it must be given as just a
+# type, without a name.
+
+BEGIN {
+ print "// This file was automatically generated by mksyscall.awk"
+ print ""
+ print "package syscall"
+ print ""
+ print "import \"unsafe\""
+ print ""
+ status = 0
+}
+
+/^\/\/sys/ {
+ if ($1 == "//sysnb") {
+ blocking = 0
+ } else {
+ blocking = 1
+ }
+
+ if (match($0, "//sys(nb)?[ ]*([a-zA-Z0-9_]+)\\(([^()]*)\\) *(\\(([^()]+)\\))?", gosig) == 0) {
+ print "unmatched line:", $0 | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ gofnname = gosig[2]
+ gofnparams = gosig[3]
+ gofnresults = gosig[5]
+
+ getline
+
+ if (match($0, "//([a-zA-Z0-9_]+)\\(([^()]*)\\) *(.*)$", csig) == 0) {
+ print "unmatched C line", $0, "after", gofnname | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ cfnname = csig[1]
+ cfnparams = csig[2]
+ cfnresult = csig[3]
+
+ printf("// Automatically generated wrapper for %s/%s\n", gofnname, cfnname)
+ printf("func c_%s(%s) %s%s__asm__(\"%s\")\n",
+ cfnname, cfnparams, cfnresult, cfnresult == "" ? "" : " ", cfnname)
+ printf("func %s(%s) %s%s{\n",
+ gofnname, gofnparams, gosig[4], gosig[4] == "" ? "" : " ")
+
+ if (blocking) {
+ print "\tentersyscall()"
+ }
+
+ loc = gofnname "/" cfnname ":"
+
+ split(gofnparams, goargs, ", *")
+ split(cfnparams, cargs, ", *")
+ args = ""
+ carg = 1
+ for (goarg = 1; goargs[goarg] != ""; goarg++) {
+ if (cargs[carg] == "") {
+ print loc, "not enough C parameters"
+ }
+
+ if (args != "") {
+ args = args ", "
+ }
+
+ if (match(goargs[goarg], "^([^ ]*) ([^ ]*)$", goparam) == 0) {
+ print loc, "bad parameter:", goargs[goarg] | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ goname = goparam[1]
+ gotype = goparam[2]
+
+ if (match(cargs[carg], "^([^ ]*) ([^ ]*)$", cparam) == 0) {
+ print loc, "bad C parameter:", cargs[carg] | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ ctype = cparam[2]
+
+ if (gotype ~ /^\*/) {
+ if (gotype != ctype) {
+ print loc, "Go/C pointer type mismatch:", gotype, ctype | "cat 1>&2"
+ status = 1
+ next
+ }
+ args = args goname
+ } else if (gotype == "string") {
+ if (ctype != "*byte") {
+ print loc, "Go string not matched to C *byte:", gotype, ctype | "cat 1>&2"
+ status = 1
+ next
+ }
+ args = args "StringBytePtr(" goname ")"
+ } else if (gotype ~ /^\[\](.*)/) {
+ if (ctype !~ /^\*/ || cargs[carg + 1] == "") {
+ print loc, "bad C type for slice:", gotype, ctype | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ # Convert a slice into a pair of pointer, length.
+ # Don't try to take the address of the zeroth element of a
+ # nil slice.
+ printf("\tvar _p%d %s\n", goarg, ctype)
+ printf("\tif len(%s) > 0 {\n", goname)
+ printf("\t\t_p%d = (%s)(unsafe.Pointer(&%s[0]))\n", goarg, ctype, goname)
+ printf("\t} else {\n")
+ printf("\t\t_p%d = (%s)(unsafe.Pointer(&_zero))\n", goarg, ctype)
+ printf("\t}\n")
+
+ ++carg
+ if (match(cargs[carg], "^([^ ]*) ([^ ]*)$", cparam) == 0) {
+ print loc, "bad C parameter:", cargs[carg] | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ args = sprintf("%s_p%d, %s(len(%s))", args, goarg, cparam[2], goname)
+ } else if (gotype == "uintptr" && ctype ~ /^\*/) {
+ args = sprintf("%s(%s)(unsafe.Pointer(%s))", args, ctype, goname)
+ } else {
+ args = sprintf("%s%s(%s)", args, ctype, goname)
+ }
+
+ carg++
+ }
+
+ if (cargs[carg] != "") {
+ print loc, "too many C parameters" | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ printf("\t")
+ if (gofnresults != "") {
+ printf("_r := ")
+ }
+ printf("c_%s(%s)\n", cfnname, args)
+
+ if (gofnresults != "") {
+ fields = split(gofnresults, goresults, ", *")
+ if (fields > 2) {
+ print loc, "too many Go results" | "cat 1>&2"
+ status = 1
+ next
+ }
+ usedr = 0
+ for (goresult = 1; goresults[goresult] != ""; goresult++) {
+ if (match(goresults[goresult], "^([^ ]*) ([^ ]*)$", goparam) == 0) {
+ print loc, "bad result:", goresults[goresult] | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ goname = goparam[1]
+ gotype = goparam[2]
+
+ if (goname == "errno") {
+ if (cfnresult ~ /^\*/) {
+ print "\tif _r == nil {"
+ } else {
+ print "\tif _r < 0 {"
+ }
+ print "\t\terrno = GetErrno()"
+ print "\t}"
+ } else if (gotype == "uintptr" && cfnresult ~ /^\*/) {
+ printf("\t%s = (%s)(unsafe.Pointer(_r))\n", goname, gotype)
+ } else {
+ if (usedr) {
+ print loc, "two parameters but no errno parameter" | "cat 1>&2"
+ status = 1
+ next
+ }
+ printf("\t%s = (%s)(_r)\n", goname, gotype)
+ usedr = 1
+ }
+ }
+ }
+
+ if (blocking) {
+ print "\texitsyscall()"
+ }
+
+ if (gofnresults != "") {
+ print "\treturn"
+ }
+
+ print "}"
+
+ print ""
+
+ next
+}
+
+{ next }
+
+END {
+ if (status != 0) {
+ print "*** mksyscall.awk failed" | "cat 1>&2"
+ exit status
+ }
+}
diff --git a/libgo/go/syscall/netlink_linux.go b/libgo/go/syscall/netlink_linux.go
new file mode 100644
index 00000000000..4ee78d62f25
--- /dev/null
+++ b/libgo/go/syscall/netlink_linux.go
@@ -0,0 +1,229 @@
+// 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.
+
+// Netlink sockets and messages
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+// Round the length of a netlink message up to align it properly.
+func nlmAlignOf(msglen int) int {
+ return (msglen + NLMSG_ALIGNTO - 1) & ^(NLMSG_ALIGNTO - 1)
+}
+
+// Round the length of a netlink route attribute up to align it
+// properly.
+func rtaAlignOf(attrlen int) int {
+ return (attrlen + RTA_ALIGNTO - 1) & ^(RTA_ALIGNTO - 1)
+}
+
+// NetlinkRouteRequest represents the request message to receive
+// routing and link states from the kernel.
+type NetlinkRouteRequest struct {
+ Header NlMsghdr
+ Data RtGenmsg
+}
+
+func (rr *NetlinkRouteRequest) toWireFormat() []byte {
+ b := make([]byte, rr.Header.Len)
+ b[0] = byte(rr.Header.Len)
+ b[1] = byte(rr.Header.Len >> 8)
+ b[2] = byte(rr.Header.Len >> 16)
+ b[3] = byte(rr.Header.Len >> 24)
+ b[4] = byte(rr.Header.Type)
+ b[5] = byte(rr.Header.Type >> 8)
+ b[6] = byte(rr.Header.Flags)
+ b[7] = byte(rr.Header.Flags >> 8)
+ b[8] = byte(rr.Header.Seq)
+ b[9] = byte(rr.Header.Seq >> 8)
+ b[10] = byte(rr.Header.Seq >> 16)
+ b[11] = byte(rr.Header.Seq >> 24)
+ b[12] = byte(rr.Header.Pid)
+ b[13] = byte(rr.Header.Pid >> 8)
+ b[14] = byte(rr.Header.Pid >> 16)
+ b[15] = byte(rr.Header.Pid >> 24)
+ b[16] = byte(rr.Data.Family)
+ return b
+}
+
+func newNetlinkRouteRequest(proto, seq, family int) []byte {
+ rr := &NetlinkRouteRequest{}
+ rr.Header.Len = uint32(NLMSG_HDRLEN + SizeofRtGenmsg)
+ rr.Header.Type = uint16(proto)
+ rr.Header.Flags = NLM_F_DUMP | NLM_F_REQUEST
+ rr.Header.Seq = uint32(seq)
+ rr.Data.Family = uint8(family)
+ return rr.toWireFormat()
+}
+
+// NetlinkRIB returns routing information base, as known as RIB,
+// which consists of network facility information, states and
+// parameters.
+func NetlinkRIB(proto, family int) ([]byte, int) {
+ var (
+ s int
+ e int
+ lsanl SockaddrNetlink
+ seq int
+ tab []byte
+ )
+
+ s, e = Socket(AF_NETLINK, SOCK_RAW, 0)
+ if e != 0 {
+ return nil, e
+ }
+ defer Close(s)
+
+ lsanl.Family = AF_NETLINK
+ e = Bind(s, &lsanl)
+ if e != 0 {
+ return nil, e
+ }
+
+ seq++
+ wb := newNetlinkRouteRequest(proto, seq, family)
+ e = Sendto(s, wb, 0, &lsanl)
+ if e != 0 {
+ return nil, e
+ }
+
+ for {
+ var (
+ rb []byte
+ nr int
+ lsa Sockaddr
+ )
+
+ rb = make([]byte, Getpagesize())
+ nr, _, e = Recvfrom(s, rb, 0)
+ if e != 0 {
+ return nil, e
+ }
+ if nr < NLMSG_HDRLEN {
+ return nil, EINVAL
+ }
+ rb = rb[:nr]
+ tab = append(tab, rb...)
+
+ msgs, _ := ParseNetlinkMessage(rb)
+ for _, m := range msgs {
+ if lsa, e = Getsockname(s); e != 0 {
+ return nil, e
+ }
+ switch v := lsa.(type) {
+ case *SockaddrNetlink:
+ if m.Header.Seq != uint32(seq) || m.Header.Pid != v.Pid {
+ return nil, EINVAL
+ }
+ default:
+ return nil, EINVAL
+ }
+ if m.Header.Type == NLMSG_DONE {
+ goto done
+ }
+ if m.Header.Type == NLMSG_ERROR {
+ return nil, EINVAL
+ }
+ }
+ }
+
+done:
+ return tab, 0
+}
+
+// NetlinkMessage represents the netlink message.
+type NetlinkMessage struct {
+ Header NlMsghdr
+ Data []byte
+}
+
+// ParseNetlinkMessage parses buf as netlink messages and returns
+// the slice containing the NetlinkMessage structs.
+func ParseNetlinkMessage(buf []byte) ([]NetlinkMessage, int) {
+ var (
+ h *NlMsghdr
+ dbuf []byte
+ dlen int
+ e int
+ msgs []NetlinkMessage
+ )
+
+ for len(buf) >= NLMSG_HDRLEN {
+ h, dbuf, dlen, e = netlinkMessageHeaderAndData(buf)
+ if e != 0 {
+ break
+ }
+ m := NetlinkMessage{}
+ m.Header = *h
+ m.Data = dbuf[:int(h.Len)-NLMSG_HDRLEN]
+ msgs = append(msgs, m)
+ buf = buf[dlen:]
+ }
+
+ return msgs, e
+}
+
+func netlinkMessageHeaderAndData(buf []byte) (*NlMsghdr, []byte, int, int) {
+ h := (*NlMsghdr)(unsafe.Pointer(&buf[0]))
+ if int(h.Len) < NLMSG_HDRLEN || int(h.Len) > len(buf) {
+ return nil, nil, 0, EINVAL
+ }
+ return h, buf[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), 0
+}
+
+// NetlinkRouteAttr represents the netlink route attribute.
+type NetlinkRouteAttr struct {
+ Attr RtAttr
+ Value []byte
+}
+
+// ParseNetlinkRouteAttr parses msg's payload as netlink route
+// attributes and returns the slice containing the NetlinkRouteAttr
+// structs.
+func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, int) {
+ var (
+ buf []byte
+ a *RtAttr
+ alen int
+ vbuf []byte
+ e int
+ attrs []NetlinkRouteAttr
+ )
+
+ switch msg.Header.Type {
+ case RTM_NEWLINK, RTM_DELLINK:
+ buf = msg.Data[SizeofIfInfomsg:]
+ case RTM_NEWADDR, RTM_DELADDR:
+ buf = msg.Data[SizeofIfAddrmsg:]
+ case RTM_NEWROUTE, RTM_DELROUTE:
+ buf = msg.Data[SizeofRtMsg:]
+ default:
+ return nil, EINVAL
+ }
+
+ for len(buf) >= SizeofRtAttr {
+ a, vbuf, alen, e = netlinkRouteAttrAndValue(buf)
+ if e != 0 {
+ break
+ }
+ ra := NetlinkRouteAttr{}
+ ra.Attr = *a
+ ra.Value = vbuf[:int(a.Len)-SizeofRtAttr]
+ attrs = append(attrs, ra)
+ buf = buf[alen:]
+ }
+
+ return attrs, 0
+}
+
+func netlinkRouteAttrAndValue(buf []byte) (*RtAttr, []byte, int, int) {
+ h := (*RtAttr)(unsafe.Pointer(&buf[0]))
+ if int(h.Len) < SizeofRtAttr || int(h.Len) > len(buf) {
+ return nil, nil, 0, EINVAL
+ }
+ return h, buf[SizeofRtAttr:], rtaAlignOf(int(h.Len)), 0
+}
diff --git a/libgo/go/syscall/route_bsd.go b/libgo/go/syscall/route_bsd.go
new file mode 100644
index 00000000000..f6b124b64e4
--- /dev/null
+++ b/libgo/go/syscall/route_bsd.go
@@ -0,0 +1,197 @@
+// 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.
+
+// +build darwin freebsd openbsd
+
+// Routing sockets and messages
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+// Round the length of a raw sockaddr up to align it properly.
+func rsaAlignOf(salen int) int {
+ salign := sizeofPtr
+ // NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
+ // aligned access to BSD subsystem.
+ if darwinAMD64 {
+ salign = 4
+ }
+ if salen == 0 {
+ return salign
+ }
+ return (salen + salign - 1) & ^(salign - 1)
+}
+
+// RouteRIB returns routing information base, as known as RIB,
+// which consists of network facility information, states and
+// parameters.
+func RouteRIB(facility, param int) ([]byte, int) {
+ var (
+ tab []byte
+ e int
+ )
+
+ mib := []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(facility), _C_int(param)}
+
+ // Find size.
+ n := uintptr(0)
+ if e = sysctl(mib, nil, &n, nil, 0); e != 0 {
+ return nil, e
+ }
+ if n == 0 {
+ return nil, 0
+ }
+
+ tab = make([]byte, n)
+ if e = sysctl(mib, &tab[0], &n, nil, 0); e != 0 {
+ return nil, e
+ }
+
+ return tab[:n], 0
+}
+
+// RoutingMessage represents a routing message.
+type RoutingMessage interface {
+ sockaddr() []Sockaddr
+}
+
+const anyMessageLen = int(unsafe.Sizeof(anyMessage{}))
+
+type anyMessage struct {
+ Msglen uint16
+ Version uint8
+ Type uint8
+}
+
+// RouteMessage represents a routing message containing routing
+// entries.
+type RouteMessage struct {
+ Header RtMsghdr
+ Data []byte
+}
+
+const rtaRtMask = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_GENMASK
+
+func (m *RouteMessage) sockaddr() []Sockaddr {
+ var (
+ af int
+ sas [4]Sockaddr
+ )
+
+ buf := m.Data[:]
+ for i := uint(0); i < RTAX_MAX; i++ {
+ if m.Header.Addrs&rtaRtMask&(1<<i) == 0 {
+ continue
+ }
+ rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
+ switch i {
+ case RTAX_DST, RTAX_GATEWAY:
+ sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+ if e != 0 {
+ return nil
+ }
+ if i == RTAX_DST {
+ af = int(rsa.Family)
+ }
+ sas[i] = sa
+ case RTAX_NETMASK, RTAX_GENMASK:
+ switch af {
+ case AF_INET:
+ rsa4 := (*RawSockaddrInet4)(unsafe.Pointer(&buf[0]))
+ sa := new(SockaddrInet4)
+ for j := 0; rsa4.Len > 0 && j < int(rsa4.Len)-int(unsafe.Offsetof(rsa4.Addr)); j++ {
+ sa.Addr[j] = rsa4.Addr[j]
+ }
+ sas[i] = sa
+ case AF_INET6:
+ rsa6 := (*RawSockaddrInet6)(unsafe.Pointer(&buf[0]))
+ sa := new(SockaddrInet6)
+ for j := 0; rsa6.Len > 0 && j < int(rsa6.Len)-int(unsafe.Offsetof(rsa6.Addr)); j++ {
+ sa.Addr[j] = rsa6.Addr[j]
+ }
+ sas[i] = sa
+ }
+ }
+ buf = buf[rsaAlignOf(int(rsa.Len)):]
+ }
+
+ return sas[:]
+}
+
+// InterfaceMessage represents a routing message containing
+// network interface entries.
+type InterfaceMessage struct {
+ Header IfMsghdr
+ Data []byte
+}
+
+func (m *InterfaceMessage) sockaddr() (sas []Sockaddr) {
+ if m.Header.Addrs&RTA_IFP == 0 {
+ return nil
+ }
+ sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(&m.Data[0])))
+ if e != 0 {
+ return nil
+ }
+ return append(sas, sa)
+}
+
+// InterfaceAddrMessage represents a routing message containing
+// network interface address entries.
+type InterfaceAddrMessage struct {
+ Header IfaMsghdr
+ Data []byte
+}
+
+const rtaIfaMask = RTA_IFA | RTA_NETMASK | RTA_BRD
+
+func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) {
+ if m.Header.Addrs&rtaIfaMask == 0 {
+ return nil
+ }
+
+ buf := m.Data[:]
+ for i := uint(0); i < RTAX_MAX; i++ {
+ if m.Header.Addrs&rtaIfaMask&(1<<i) == 0 {
+ continue
+ }
+ rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
+ switch i {
+ case RTAX_IFA:
+ sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+ if e != 0 {
+ return nil
+ }
+ sas = append(sas, sa)
+ case RTAX_NETMASK, RTAX_BRD:
+ // nothing to do
+ }
+ buf = buf[rsaAlignOf(int(rsa.Len)):]
+ }
+
+ return sas
+}
+
+// ParseRoutingMessage parses buf as routing messages and returns
+// the slice containing the RoutingMessage interfaces.
+func ParseRoutingMessage(buf []byte) (msgs []RoutingMessage, errno int) {
+ for len(buf) >= anyMessageLen {
+ any := (*anyMessage)(unsafe.Pointer(&buf[0]))
+ if any.Version != RTM_VERSION {
+ return nil, EINVAL
+ }
+ msgs = append(msgs, any.toRoutingMessage(buf))
+ buf = buf[any.Msglen:]
+ }
+ return msgs, 0
+}
+
+// ParseRoutingMessage parses msg's payload as raw sockaddrs and
+// returns the slice containing the Sockaddr interfaces.
+func ParseRoutingSockaddr(msg RoutingMessage) (sas []Sockaddr, errno int) {
+ return append(sas, msg.sockaddr()...), 0
+}
diff --git a/libgo/go/syscall/route_darwin.go b/libgo/go/syscall/route_darwin.go
new file mode 100644
index 00000000000..9d3a701daba
--- /dev/null
+++ b/libgo/go/syscall/route_darwin.go
@@ -0,0 +1,77 @@
+// 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.
+
+// Routing sockets and messages for Darwin
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage {
+ switch any.Type {
+ case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
+ p := (*RouteMessage)(unsafe.Pointer(any))
+ rtm := &RouteMessage{}
+ rtm.Header = p.Header
+ rtm.Data = buf[SizeofRtMsghdr:any.Msglen]
+ return rtm
+ case RTM_IFINFO:
+ p := (*InterfaceMessage)(unsafe.Pointer(any))
+ ifm := &InterfaceMessage{}
+ ifm.Header = p.Header
+ ifm.Data = buf[SizeofIfMsghdr:any.Msglen]
+ return ifm
+ case RTM_NEWADDR, RTM_DELADDR:
+ p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
+ ifam := &InterfaceAddrMessage{}
+ ifam.Header = p.Header
+ ifam.Data = buf[SizeofIfaMsghdr:any.Msglen]
+ return ifam
+ case RTM_NEWMADDR2, RTM_DELMADDR:
+ p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any))
+ ifmam := &InterfaceMulticastAddrMessage{}
+ ifmam.Header = p.Header
+ ifmam.Data = buf[SizeofIfmaMsghdr2:any.Msglen]
+ return ifmam
+ }
+ return nil
+}
+
+// InterfaceMulticastAddrMessage represents a routing message
+// containing network interface address entries.
+type InterfaceMulticastAddrMessage struct {
+ Header IfmaMsghdr2
+ Data []byte
+}
+
+const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA
+
+func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
+ if m.Header.Addrs&rtaIfmaMask == 0 {
+ return nil
+ }
+
+ buf := m.Data[:]
+ for i := uint(0); i < RTAX_MAX; i++ {
+ if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 {
+ continue
+ }
+ rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
+ switch i {
+ case RTAX_IFA:
+ sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+ if e != 0 {
+ return nil
+ }
+ sas = append(sas, sa)
+ case RTAX_GATEWAY, RTAX_IFP:
+ // nothing to do
+ }
+ buf = buf[rsaAlignOf(int(rsa.Len)):]
+ }
+
+ return sas
+}
diff --git a/libgo/go/syscall/route_freebsd.go b/libgo/go/syscall/route_freebsd.go
new file mode 100644
index 00000000000..0d61d08b08c
--- /dev/null
+++ b/libgo/go/syscall/route_freebsd.go
@@ -0,0 +1,77 @@
+// 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.
+
+// Routing sockets and messages for FreeBSD
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage {
+ switch any.Type {
+ case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
+ p := (*RouteMessage)(unsafe.Pointer(any))
+ rtm := &RouteMessage{}
+ rtm.Header = p.Header
+ rtm.Data = buf[SizeofRtMsghdr:any.Msglen]
+ return rtm
+ case RTM_IFINFO:
+ p := (*InterfaceMessage)(unsafe.Pointer(any))
+ ifm := &InterfaceMessage{}
+ ifm.Header = p.Header
+ ifm.Data = buf[SizeofIfMsghdr:any.Msglen]
+ return ifm
+ case RTM_NEWADDR, RTM_DELADDR:
+ p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
+ ifam := &InterfaceAddrMessage{}
+ ifam.Header = p.Header
+ ifam.Data = buf[SizeofIfaMsghdr:any.Msglen]
+ return ifam
+ case RTM_NEWMADDR, RTM_DELMADDR:
+ p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any))
+ ifmam := &InterfaceMulticastAddrMessage{}
+ ifmam.Header = p.Header
+ ifmam.Data = buf[SizeofIfmaMsghdr:any.Msglen]
+ return ifmam
+ }
+ return nil
+}
+
+// InterfaceMulticastAddrMessage represents a routing message
+// containing network interface address entries.
+type InterfaceMulticastAddrMessage struct {
+ Header IfmaMsghdr
+ Data []byte
+}
+
+const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA
+
+func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
+ if m.Header.Addrs&rtaIfmaMask == 0 {
+ return nil
+ }
+
+ buf := m.Data[:]
+ for i := uint(0); i < RTAX_MAX; i++ {
+ if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 {
+ continue
+ }
+ rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
+ switch i {
+ case RTAX_IFA:
+ sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+ if e != 0 {
+ return nil
+ }
+ sas = append(sas, sa)
+ case RTAX_GATEWAY, RTAX_IFP:
+ // nothing to do
+ }
+ buf = buf[rsaAlignOf(int(rsa.Len)):]
+ }
+
+ return sas
+}
diff --git a/libgo/go/syscall/route_openbsd.go b/libgo/go/syscall/route_openbsd.go
new file mode 100644
index 00000000000..30e1cac46fc
--- /dev/null
+++ b/libgo/go/syscall/route_openbsd.go
@@ -0,0 +1,35 @@
+// 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.
+
+// Routing sockets and messages for OpenBSD
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage {
+ switch any.Type {
+ case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
+ p := (*RouteMessage)(unsafe.Pointer(any))
+ rtm := &RouteMessage{}
+ rtm.Header = p.Header
+ rtm.Data = buf[SizeofRtMsghdr:any.Msglen]
+ return rtm
+ case RTM_IFINFO:
+ p := (*InterfaceMessage)(unsafe.Pointer(any))
+ ifm := &InterfaceMessage{}
+ ifm.Header = p.Header
+ ifm.Data = buf[SizeofIfMsghdr:any.Msglen]
+ return ifm
+ case RTM_NEWADDR, RTM_DELADDR:
+ p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
+ ifam := &InterfaceAddrMessage{}
+ ifam.Header = p.Header
+ ifam.Data = buf[SizeofIfaMsghdr:any.Msglen]
+ return ifam
+ }
+ return nil
+}
diff --git a/libgo/go/syscall/sleep_rtems.go b/libgo/go/syscall/sleep_rtems.go
new file mode 100644
index 00000000000..8992eb53c3e
--- /dev/null
+++ b/libgo/go/syscall/sleep_rtems.go
@@ -0,0 +1,13 @@
+// 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.
+
+package syscall
+
+func Sleep(nsec int64) (errno int) {
+ ts := NsecToTimespec(nsec)
+ errno = Nanosleep(&ts, nil)
+ return
+}
diff --git a/libgo/go/syscall/sleep_select.go b/libgo/go/syscall/sleep_select.go
new file mode 100644
index 00000000000..3ebaf58f969
--- /dev/null
+++ b/libgo/go/syscall/sleep_select.go
@@ -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);
+ _, err := Select(0, nil, nil, nil, &tv);
+ return err;
+}
diff --git a/libgo/go/syscall/sockcmsg_linux.go b/libgo/go/syscall/sockcmsg_linux.go
new file mode 100644
index 00000000000..b025ca52101
--- /dev/null
+++ b/libgo/go/syscall/sockcmsg_linux.go
@@ -0,0 +1,38 @@
+// 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.
+
+// Socket control messages
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+// UnixCredentials encodes credentials into a socket control message
+// for sending to another process. This can be used for
+// authentication.
+func UnixCredentials(ucred *Ucred) []byte {
+ buf := make([]byte, CmsgSpace(SizeofUcred))
+ cmsg := (*Cmsghdr)(unsafe.Pointer(&buf[0]))
+ cmsg.Level = SOL_SOCKET
+ cmsg.Type = SCM_CREDENTIALS
+ cmsg.SetLen(CmsgLen(SizeofUcred))
+ *((*Ucred)(cmsgData(cmsg))) = *ucred
+ return buf
+}
+
+// ParseUnixCredentials decodes a socket control message that contains
+// credentials in a Ucred structure. To receive such a message, the
+// SO_PASSCRED option must be enabled on the socket.
+func ParseUnixCredentials(msg *SocketControlMessage) (*Ucred, int) {
+ if msg.Header.Level != SOL_SOCKET {
+ return nil, EINVAL
+ }
+ if msg.Header.Type != SCM_CREDENTIALS {
+ return nil, EINVAL
+ }
+ ucred := *(*Ucred)(unsafe.Pointer(&msg.Data[0]))
+ return &ucred, 0
+}
diff --git a/libgo/go/syscall/sockcmsg_unix.go b/libgo/go/syscall/sockcmsg_unix.go
new file mode 100644
index 00000000000..c9872aeba31
--- /dev/null
+++ b/libgo/go/syscall/sockcmsg_unix.go
@@ -0,0 +1,115 @@
+// 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.
+
+// +build darwin freebsd linux openbsd
+
+// Socket control messages
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+// Round the length of a raw sockaddr up to align it propery.
+func cmsgAlignOf(salen int) int {
+ salign := sizeofPtr
+ // NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
+ // aligned access to BSD subsystem.
+ if darwinAMD64 {
+ salign = 4
+ }
+ if salen == 0 {
+ return salign
+ }
+ return (salen + salign - 1) & ^(salign - 1)
+}
+
+// CmsgLen returns the value to store in the Len field of the Cmsghdr
+// structure, taking into account any necessary alignment.
+func CmsgLen(datalen int) int {
+ return cmsgAlignOf(SizeofCmsghdr) + datalen
+}
+
+// CmsgSpace returns the number of bytes an ancillary element with
+// payload of the passed data length occupies.
+func CmsgSpace(datalen int) int {
+ return cmsgAlignOf(SizeofCmsghdr) + cmsgAlignOf(datalen)
+}
+
+func cmsgData(cmsg *Cmsghdr) unsafe.Pointer {
+ return unsafe.Pointer(uintptr(unsafe.Pointer(cmsg)) + SizeofCmsghdr)
+}
+
+type SocketControlMessage struct {
+ Header Cmsghdr
+ Data []byte
+}
+
+func ParseSocketControlMessage(buf []byte) ([]SocketControlMessage, int) {
+ var (
+ h *Cmsghdr
+ dbuf []byte
+ e int
+ cmsgs []SocketControlMessage
+ )
+
+ for len(buf) >= CmsgLen(0) {
+ h, dbuf, e = socketControlMessageHeaderAndData(buf)
+ if e != 0 {
+ break
+ }
+ m := SocketControlMessage{}
+ m.Header = *h
+ m.Data = dbuf[:int(h.Len)-cmsgAlignOf(SizeofCmsghdr)]
+ cmsgs = append(cmsgs, m)
+ buf = buf[cmsgAlignOf(int(h.Len)):]
+ }
+
+ return cmsgs, e
+}
+
+func socketControlMessageHeaderAndData(buf []byte) (*Cmsghdr, []byte, int) {
+ h := (*Cmsghdr)(unsafe.Pointer(&buf[0]))
+ if h.Len < SizeofCmsghdr || int(h.Len) > len(buf) {
+ return nil, nil, EINVAL
+ }
+ return h, buf[cmsgAlignOf(SizeofCmsghdr):], 0
+}
+
+// UnixRights encodes a set of open file descriptors into a socket
+// control message for sending to another process.
+func UnixRights(fds ...int) []byte {
+ datalen := len(fds) * 4
+ buf := make([]byte, CmsgSpace(datalen))
+ cmsg := (*Cmsghdr)(unsafe.Pointer(&buf[0]))
+ cmsg.Level = SOL_SOCKET
+ cmsg.Type = SCM_RIGHTS
+ cmsg.SetLen(CmsgLen(datalen))
+
+ data := uintptr(cmsgData(cmsg))
+ for _, fd := range fds {
+ *(*int32)(unsafe.Pointer(data)) = int32(fd)
+ data += 4
+ }
+
+ return buf
+}
+
+// ParseUnixRights decodes a socket control message that contains an
+// integer array of open file descriptors from another process.
+func ParseUnixRights(msg *SocketControlMessage) ([]int, int) {
+ if msg.Header.Level != SOL_SOCKET {
+ return nil, EINVAL
+ }
+ if msg.Header.Type != SCM_RIGHTS {
+ return nil, EINVAL
+ }
+ fds := make([]int, len(msg.Data)>>2)
+ for i, j := 0, 0; i < len(msg.Data); i += 4 {
+ fds[j] = int(*(*int32)(unsafe.Pointer(&msg.Data[i])))
+ j++
+ }
+ return fds, 0
+}
diff --git a/libgo/go/syscall/socket.go b/libgo/go/syscall/socket.go
new file mode 100644
index 00000000000..9da8a686e3e
--- /dev/null
+++ b/libgo/go/syscall/socket.go
@@ -0,0 +1,423 @@
+// socket.go -- Socket handling.
+
+// Copyright 2009 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.
+
+// Low-level socket interface.
+// Only for implementing net package.
+// DO NOT USE DIRECTLY.
+
+package syscall
+
+import "unsafe"
+
+// For testing: clients can set this flag to force
+// creation of IPv6 sockets to return EAFNOSUPPORT.
+var SocketDisableIPv6 bool
+
+type Sockaddr interface {
+ sockaddr() (ptr *RawSockaddrAny, len Socklen_t, errno int) // lowercase; only we can define Sockaddrs
+}
+
+type RawSockaddrAny struct {
+ Addr RawSockaddr
+ Pad [12]int8
+}
+
+const SizeofSockaddrAny = 0x1c
+
+type SockaddrInet4 struct {
+ Port int
+ Addr [4]byte
+ raw RawSockaddrInet4
+}
+
+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
+}
+
+type SockaddrInet6 struct {
+ Port int
+ ZoneId uint32
+ Addr [16]byte
+ raw RawSockaddrInet6
+}
+
+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)
+ sa.raw.Scope_id = sa.ZoneId
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.raw.Addr[i] = sa.Addr[i]
+ }
+ return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, 0
+}
+
+type SockaddrUnix struct {
+ Name string
+ raw RawSockaddrUnix
+}
+
+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 anyToSockaddrOS(rsa)
+}
+
+//sys accept(fd int, sa *RawSockaddrAny, len *Socklen_t) (nfd int, errno int)
+//accept(fd int, sa *RawSockaddrAny, len *Socklen_t) int
+
+func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
+ var rsa RawSockaddrAny
+ var len Socklen_t = SizeofSockaddrAny
+ nfd, errno = accept(fd, &rsa, &len)
+ if errno != 0 {
+ return
+ }
+ sa, errno = anyToSockaddr(&rsa)
+ if errno != 0 {
+ Close(nfd)
+ nfd = 0
+ }
+ return
+}
+
+//sysnb getsockname(fd int, sa *RawSockaddrAny, len *Socklen_t) (errno int)
+//getsockname(fd int, sa *RawSockaddrAny, len *Socklen_t) int
+
+func Getsockname(fd int) (sa Sockaddr, errno int) {
+ var rsa RawSockaddrAny
+ var len Socklen_t = SizeofSockaddrAny
+ if errno = getsockname(fd, &rsa, &len); errno != 0 {
+ return
+ }
+ return anyToSockaddr(&rsa)
+}
+
+//sysnb getpeername(fd int, sa *RawSockaddrAny, len *Socklen_t) (errno int)
+//getpeername(fd int, sa *RawSockaddrAny, len *Socklen_t) int
+
+func Getpeername(fd int) (sa Sockaddr, errno int) {
+ var rsa RawSockaddrAny
+ var len Socklen_t = SizeofSockaddrAny
+ if getpeername(fd, &rsa, &len); errno != 0 {
+ return
+ }
+ return anyToSockaddr(&rsa)
+}
+
+//sys bind(fd int, sa *RawSockaddrAny, len Socklen_t) (errno int)
+//bind(fd int, sa *RawSockaddrAny, len Socklen_t) int
+
+func Bind(fd int, sa Sockaddr) (errno int) {
+ ptr, n, err := sa.sockaddr()
+ if err != 0 {
+ return err
+ }
+ return bind(fd, ptr, n)
+}
+
+//sys connect(s int, addr *RawSockaddrAny, addrlen Socklen_t) (errno int)
+//connect(s int, addr *RawSockaddrAny, addrlen Socklen_t) int
+
+func Connect(fd int, sa Sockaddr) (errno int) {
+ ptr, n, err := sa.sockaddr()
+ if err != 0 {
+ return err
+ }
+ return connect(fd, ptr, n)
+}
+
+//sysnb socket(domain int, typ int, proto int) (fd int, errno int)
+//socket(domain int, typ int, protocol int) int
+
+func Socket(domain, typ, proto int) (fd, errno int) {
+ if domain == AF_INET6 && SocketDisableIPv6 {
+ return -1, EAFNOSUPPORT
+ }
+ fd, errno = socket(domain, typ, proto)
+ return
+}
+
+//sysnb socketpair(domain int, typ int, proto int, fd *[2]int) (errno int)
+//socketpair(domain int, typ int, protocol int, fd *[2]int) int
+
+func Socketpair(domain, typ, proto int) (fd [2]int, errno int) {
+ errno = socketpair(domain, typ, proto, &fd)
+ return
+}
+
+//sys getsockopt(s int, level int, name int, val uintptr, vallen *Socklen_t) (errno int)
+//getsockopt(s int, level int, name int, val *byte, vallen *Socklen_t) int
+
+func GetsockoptInt(fd, level, opt int) (value, errno int) {
+ var n int32
+ vallen := Socklen_t(4)
+ errno = getsockopt(fd, level, opt, (uintptr)(unsafe.Pointer(&n)), &vallen)
+ return int(n), errno
+}
+
+func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, errno int) {
+ vallen := Socklen_t(4)
+ errno = getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value[0])), &vallen)
+ return value, errno
+}
+
+func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, int) {
+ var value IPMreq
+ vallen := Socklen_t(SizeofIPMreq)
+ errno := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
+ return &value, errno
+}
+
+/* FIXME: mksysinfo needs to support IPMreqn.
+
+func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, int) {
+ var value IPMreqn
+ vallen := Socklen_t(SizeofIPMreqn)
+ errno := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
+ return &value, errno
+}
+
+*/
+
+/* FIXME: mksysinfo needs to support IPv6Mreq.
+
+func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, int) {
+ var value IPv6Mreq
+ vallen := Socklen_t(SizeofIPv6Mreq)
+ errno := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
+ return &value, errno
+}
+
+*/
+
+//sys setsockopt(s int, level int, name int, val *byte, vallen Socklen_t) (errno int)
+//setsockopt(s int, level int, optname int, val *byte, vallen Socklen_t) int
+
+func SetsockoptInt(fd, level, opt int, value int) (errno int) {
+ var n = int32(value)
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&n)), 4)
+}
+
+func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (errno int) {
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&value[0])), 4)
+}
+
+func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(tv)), Socklen_t(unsafe.Sizeof(*tv)))
+}
+
+type Linger struct {
+ Onoff int32;
+ Linger int32;
+}
+
+func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(l)), Socklen_t(unsafe.Sizeof(*l)));
+}
+
+func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (errno int) {
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(mreq)), Socklen_t(unsafe.Sizeof(*mreq)))
+}
+
+/* FIXME: mksysinfo needs to support IMPreqn.
+
+func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (errno int) {
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(mreq)), Socklen_t(unsafe.Sizeof(*mreq)))
+}
+
+*/
+
+/* FIXME: mksysinfo needs to support IPv6Mreq.
+
+func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (errno int) {
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(mreq)), Socklen_t(unsafe.Sizeof(*mreq)))
+}
+
+*/
+
+func SetsockoptString(fd, level, opt int, s string) (errno int) {
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&[]byte(s)[0])), Socklen_t(len(s)))
+}
+
+//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *Socklen_t) (n int, errno int)
+//recvfrom(fd int, buf *byte, len Size_t, flags int, from *RawSockaddrAny, fromlen *Socklen_t) Ssize_t
+
+func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
+ var rsa RawSockaddrAny
+ var len Socklen_t = SizeofSockaddrAny
+ if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 {
+ return
+ }
+ from, errno = anyToSockaddr(&rsa)
+ return
+}
+
+//sys sendto(s int, buf []byte, flags int, to *RawSockaddrAny, tolen Socklen_t) (errno int)
+//sendto(s int, buf *byte, len Size_t, flags int, to *RawSockaddrAny, tolen Socklen_t) Ssize_t
+
+func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
+ ptr, n, err := to.sockaddr()
+ if err != 0 {
+ return err
+ }
+ return sendto(fd, p, flags, ptr, n)
+}
+
+//sys recvmsg(s int, msg *Msghdr, flags int) (n int, errno int)
+//recvmsg(s int, msg *Msghdr, flags int) Ssize_t
+
+func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, errno int) {
+ var msg Msghdr
+ var rsa RawSockaddrAny
+ msg.Name = (*byte)(unsafe.Pointer(&rsa))
+ msg.Namelen = uint32(SizeofSockaddrAny)
+ var iov Iovec
+ if len(p) > 0 {
+ iov.Base = (*byte)(unsafe.Pointer(&p[0]))
+ iov.SetLen(len(p))
+ }
+ var dummy byte
+ if len(oob) > 0 {
+ // receive at least one normal byte
+ if len(p) == 0 {
+ iov.Base = &dummy
+ iov.SetLen(1)
+ }
+ msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
+ msg.SetControllen(len(oob))
+ }
+ msg.Iov = &iov
+ msg.Iovlen = 1
+ if n, errno = recvmsg(fd, &msg, flags); errno != 0 {
+ return
+ }
+ oobn = int(msg.Controllen)
+ recvflags = int(msg.Flags)
+ // source address is only specified if the socket is unconnected
+ if rsa.Addr.Family != AF_UNSPEC {
+ from, errno = anyToSockaddr(&rsa)
+ }
+ return
+}
+
+//sys sendmsg(s int, msg *Msghdr, flags int) (errno int)
+//sendmsg(s int, msg *Msghdr, flags int) Ssize_t
+
+func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (errno int) {
+ var ptr *RawSockaddrAny
+ var salen Socklen_t
+ if to != nil {
+ var err int
+ ptr, salen, err = to.sockaddr()
+ if err != 0 {
+ return err
+ }
+ }
+ var msg Msghdr
+ msg.Name = (*byte)(unsafe.Pointer(ptr))
+ msg.Namelen = uint32(salen)
+ var iov Iovec
+ if len(p) > 0 {
+ iov.Base = (*byte)(unsafe.Pointer(&p[0]))
+ iov.SetLen(len(p))
+ }
+ var dummy byte
+ if len(oob) > 0 {
+ // send at least one normal byte
+ if len(p) == 0 {
+ iov.Base = &dummy
+ iov.SetLen(1)
+ }
+ msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
+ msg.SetControllen(len(oob))
+ }
+ msg.Iov = &iov
+ msg.Iovlen = 1
+ if errno = sendmsg(fd, &msg, flags); errno != 0 {
+ return
+ }
+ return
+}
+
+//sys Listen(fd int, n int) (errno int)
+//listen(fd int, n int) int
+
+//sys Shutdown(fd int, how int) (errno int)
+//shutdown(fd int, how int) int
+
+func (iov *Iovec) SetLen(length int) {
+ iov.Len = Iovec_len_t(length)
+}
+
+func (msghdr *Msghdr) SetControllen(length int) {
+ msghdr.Controllen = Msghdr_controllen_t(length)
+}
diff --git a/libgo/go/syscall/socket_bsd.go b/libgo/go/syscall/socket_bsd.go
new file mode 100644
index 00000000000..735baf98684
--- /dev/null
+++ b/libgo/go/syscall/socket_bsd.go
@@ -0,0 +1,78 @@
+// socket_bsd.go -- Socket handling specific to *BSD based systems.
+
+// 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 = 28
+const SizeofSockaddrUnix = 110
+
+type RawSockaddrInet4 struct {
+ Len uint8;
+ Family uint8;
+ Port uint16;
+ Addr [4]byte /* in_addr */;
+ Zero [8]uint8;
+}
+
+func (sa *RawSockaddrInet4) setLen() Socklen_t {
+ sa.Len = SizeofSockaddrInet4
+ return SizeofSockaddrInet4
+}
+
+type RawSockaddrInet6 struct {
+ Len uint8;
+ Family uint8;
+ Port uint16;
+ Flowinfo uint32;
+ Addr [16]byte /* in6_addr */;
+ Scope_id uint32;
+}
+
+func (sa *RawSockaddrInet6) setLen() Socklen_t {
+ sa.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;
+}
+
+// BindToDevice binds the socket associated with fd to device.
+func BindToDevice(fd int, device string) (errno int) {
+ return ENOSYS
+}
+
+func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, int) {
+ return nil, EAFNOSUPPORT;
+}
diff --git a/libgo/go/syscall/socket_irix.go b/libgo/go/syscall/socket_irix.go
new file mode 100644
index 00000000000..6f2aaaff4d0
--- /dev/null
+++ b/libgo/go/syscall/socket_irix.go
@@ -0,0 +1,129 @@
+// socket_irix.go -- Socket handling specific to IRIX 6.
+
+// 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
+
+const SizeofSockaddrInet4 = 16
+const SizeofSockaddrInet6 = 28
+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
+}
+
+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
+}
+
+// struct ip_mreg is provived in <netinet/in.h>, but protected with _SGIAPI.
+// This could be enabled with -D_SGI_SOURCE, but conflicts with
+// -D_XOPEN_SOURCE=500 required for msg_control etc. in struct msghgr, so
+// simply provide it here.
+type IPMreq struct {
+ Multiaddr [4]byte
+ Interface [4]byte
+}
+
+// Similarly, <netdb.h> only provides struct addrinfo, AI_* and EAI_* if
+// _NO_XOPEN4 && _NO_XOPEN5.
+type Addrinfo struct {
+ Ai_flags int32
+ Ai_family int32
+ Ai_socktype int32
+ Ai_protocol int32
+ Ai_addrlen int32
+ Ai_canonname *uint8
+ Ai_addr *_sockaddr
+ Ai_next *Addrinfo
+}
+
+const (
+ AI_PASSIVE = 0x00000001
+ AI_CANONNAME = 0x00000002
+ AI_NUMERICHOST = 0x00000004
+ AI_NUMERICSERV = 0x00000008
+ AI_ALL = 0x00000100
+ AI_ADDRCONFIG = 0x00000400
+ AI_V4MAPPED = 0x00000800
+ AI_DEFAULT = (AI_V4MAPPED | AI_ADDRCONFIG)
+)
+
+const (
+ EAI_ADDRFAMILY = 1
+ EAI_AGAIN = 2
+ EAI_BADFLAGS = 3
+ EAI_FAIL = 4
+ EAI_FAMILY = 5
+ EAI_MEMORY = 6
+ EAI_NODATA = 7
+ EAI_NONAME = 8
+ EAI_SERVICE = 9
+ EAI_SOCKTYPE = 10
+ EAI_SYSTEM = 11
+ EAI_BADHINTS = 12
+ EAI_OVERFLOW = 13
+ EAI_MAX = 14
+)
+
+func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, int) {
+ return nil, EAFNOSUPPORT;
+}
diff --git a/libgo/go/syscall/socket_linux.go b/libgo/go/syscall/socket_linux.go
new file mode 100644
index 00000000000..20a37f7390b
--- /dev/null
+++ b/libgo/go/syscall/socket_linux.go
@@ -0,0 +1,183 @@
+// socket_linux.go -- Socket handling specific to Linux.
+
+// 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
+
+import "unsafe"
+
+const SizeofSockaddrInet4 = 16
+const SizeofSockaddrInet6 = 28
+const SizeofSockaddrUnix = 110
+const SizeofSockaddrLinklayer = 20
+const SizeofSockaddrNetlink = 12
+
+type SockaddrLinklayer struct {
+ Protocol uint16
+ Ifindex int
+ Hatype uint16
+ Pkttype uint8
+ Halen uint8
+ Addr [8]byte
+ raw RawSockaddrLinklayer
+}
+
+func (sa *SockaddrLinklayer) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+ if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff {
+ return nil, 0, EINVAL
+ }
+ sa.raw.Family = AF_PACKET
+ sa.raw.Protocol = sa.Protocol
+ sa.raw.Ifindex = int32(sa.Ifindex)
+ sa.raw.Hatype = sa.Hatype
+ sa.raw.Pkttype = sa.Pkttype
+ sa.raw.Halen = sa.Halen
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.raw.Addr[i] = sa.Addr[i]
+ }
+ return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrLinklayer, 0
+}
+
+type SockaddrNetlink struct {
+ Family uint16
+ Pad uint16
+ Pid uint32
+ Groups uint32
+ raw RawSockaddrNetlink
+}
+
+func (sa *SockaddrNetlink) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+ sa.raw.Family = AF_NETLINK
+ sa.raw.Pad = sa.Pad
+ sa.raw.Pid = sa.Pid
+ sa.raw.Groups = sa.Groups
+ return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrNetlink, 0
+}
+
+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
+}
+
+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 RawSockaddrLinklayer struct {
+ Family uint16
+ Protocol uint16
+ Ifindex int32
+ Hatype uint16
+ Pkttype uint8
+ Halen uint8
+ Addr [8]uint8
+}
+
+type RawSockaddrNetlink struct {
+ Family uint16
+ Pad uint16
+ Pid uint32
+ Groups uint32
+}
+
+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 SetsockoptString(fd, SOL_SOCKET, SO_BINDTODEVICE, device)
+}
+
+func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, int) {
+ switch rsa.Addr.Family {
+ case AF_NETLINK:
+ pp := (*RawSockaddrNetlink)(unsafe.Pointer(rsa))
+ sa := new(SockaddrNetlink)
+ sa.Family = pp.Family
+ sa.Pad = pp.Pad
+ sa.Pid = pp.Pid
+ sa.Groups = pp.Groups
+ return sa, 0
+
+ case AF_PACKET:
+ pp := (*RawSockaddrLinklayer)(unsafe.Pointer(rsa))
+ sa := new(SockaddrLinklayer)
+ sa.Protocol = pp.Protocol
+ sa.Ifindex = int(pp.Ifindex)
+ sa.Hatype = pp.Hatype
+ sa.Pkttype = pp.Pkttype
+ sa.Halen = pp.Halen
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.Addr[i] = pp.Addr[i]
+ }
+ return sa, 0
+ }
+ return nil, EAFNOSUPPORT
+}
+
+// We don't take this type directly from the header file because it
+// uses a union. FIXME.
+
+type EpollEvent struct {
+ Events uint32
+ Fd int32
+ Pad int32
+}
+
+//sysnb EpollCreate(size int) (fd int, errno int)
+//epoll_create(size int) int
+
+//sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (errno int)
+//epoll_ctl(epfd int, op int, fd int, event *EpollEvent) int
+
+//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, errno int)
+//epoll_wait(epfd int, events *EpollEvent, maxevents int, timeout int) int
diff --git a/libgo/go/syscall/socket_solaris.go b/libgo/go/syscall/socket_solaris.go
new file mode 100644
index 00000000000..376707858a6
--- /dev/null
+++ b/libgo/go/syscall/socket_solaris.go
@@ -0,0 +1,80 @@
+// 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
+}
+
+func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, int) {
+ return nil, EAFNOSUPPORT;
+}
diff --git a/libgo/go/syscall/str.go b/libgo/go/syscall/str.go
new file mode 100644
index 00000000000..0fce842e8c1
--- /dev/null
+++ b/libgo/go/syscall/str.go
@@ -0,0 +1,20 @@
+// Copyright 2009 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 itoa(val int) string { // do it here rather than with fmt to avoid dependency
+ if val < 0 {
+ return "-" + itoa(-val)
+ }
+ var buf [32]byte // big enough for int64
+ i := len(buf) - 1
+ for val >= 10 {
+ buf[i] = byte(val%10 + '0')
+ i--
+ val /= 10
+ }
+ buf[i] = byte(val + '0')
+ return string(buf[i:])
+}
diff --git a/libgo/go/syscall/syscall.go b/libgo/go/syscall/syscall.go
new file mode 100644
index 00000000000..a802ba0bbf2
--- /dev/null
+++ b/libgo/go/syscall/syscall.go
@@ -0,0 +1,35 @@
+// Copyright 2009 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 contains an interface to the low-level operating system
+// primitives. The details vary depending on the underlying system.
+// Its primary use is inside other packages that provide a more portable
+// interface to the system, such as "os", "time" and "net". Use those
+// packages rather than this one if you can.
+// For details of the functions and data types in this package consult
+// the manuals for the appropriate operating system.
+// These calls return errno == 0 to indicate success; otherwise
+// errno is an operating system error number describing the failure.
+package syscall
+
+import "unsafe"
+
+// StringByteSlice returns a NUL-terminated slice of bytes
+// containing the text of s.
+func StringByteSlice(s string) []byte {
+ a := make([]byte, len(s)+1)
+ copy(a, s)
+ return a
+}
+
+// StringBytePtr returns a pointer to a NUL-terminated array of bytes
+// containing the text of s.
+func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] }
+
+// Single-word zero for use when we need a valid pointer to 0 bytes.
+// See mksyscall.pl.
+var _zero uintptr
+
+var dummy *byte
+const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
diff --git a/libgo/go/syscall/syscall_linux_386.go b/libgo/go/syscall/syscall_linux_386.go
new file mode 100644
index 00000000000..aca9c7bf5ef
--- /dev/null
+++ b/libgo/go/syscall/syscall_linux_386.go
@@ -0,0 +1,15 @@
+// syscall_linux_386.go -- GNU/Linux 386 specific support
+
+// Copyright 2009 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 (r *PtraceRegs) PC() uint64 {
+ return uint64(uint32(r.Eip));
+}
+
+func (r *PtraceRegs) SetPC(pc uint64) {
+ r.Eip = int32(pc);
+}
diff --git a/libgo/go/syscall/syscall_linux_alpha.go b/libgo/go/syscall/syscall_linux_alpha.go
new file mode 100644
index 00000000000..d58f8eb13a5
--- /dev/null
+++ b/libgo/go/syscall/syscall_linux_alpha.go
@@ -0,0 +1,47 @@
+// syscall_linux_alpha.go -- GNU/Linux ALPHA specific support
+
+// 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
+
+type PtraceRegs struct {
+ R0 uint64
+ R1 uint64
+ R2 uint64
+ R3 uint64
+ R4 uint64
+ R5 uint64
+ R6 uint64
+ R7 uint64
+ R8 uint64
+ R19 uint64
+ R20 uint64
+ R21 uint64
+ R22 uint64
+ R23 uint64
+ R24 uint64
+ R25 uint64
+ R26 uint64
+ R27 uint64
+ R28 uint64
+ Hae uint64
+ Trap_a0 uint64
+ Trap_a1 uint64
+ Trap_a2 uint64
+ Ps uint64
+ Pc uint64
+ Gp uint64
+ R16 uint64
+ R17 uint64
+ R18 uint64
+}
+
+func (r *PtraceRegs) PC() uint64 {
+ return r.Pc;
+}
+
+func (r *PtraceRegs) SetPC(pc uint64) {
+ r.Pc = pc;
+}
diff --git a/libgo/go/syscall/syscall_linux_amd64.go b/libgo/go/syscall/syscall_linux_amd64.go
new file mode 100644
index 00000000000..9932579cc10
--- /dev/null
+++ b/libgo/go/syscall/syscall_linux_amd64.go
@@ -0,0 +1,15 @@
+// syscall_linux_amd64.go -- GNU/Linux 386 specific support
+
+// Copyright 2009 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 (r *PtraceRegs) PC() uint64 {
+ return r.Rip;
+}
+
+func (r *PtraceRegs) SetPC(pc uint64) {
+ r.Rip = pc;
+}
diff --git a/libgo/go/syscall/syscall_stubs.go b/libgo/go/syscall/syscall_stubs.go
new file mode 100644
index 00000000000..76c05cb546a
--- /dev/null
+++ b/libgo/go/syscall/syscall_stubs.go
@@ -0,0 +1,27 @@
+// 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.
+
+// These are stubs.
+
+package syscall
+
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+ z := -1
+ return uintptr(z), 0, uintptr(ENOSYS)
+}
+
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+ z := -1
+ return uintptr(z), 0, uintptr(ENOSYS)
+}
+
+func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+ z := -1
+ return uintptr(z), 0, uintptr(ENOSYS)
+}
+
+func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+ z := -1
+ return uintptr(z), 0, uintptr(ENOSYS)
+}
diff --git a/libgo/go/syscall/syscall_unix.go b/libgo/go/syscall/syscall_unix.go
new file mode 100644
index 00000000000..c734b2cf06a
--- /dev/null
+++ b/libgo/go/syscall/syscall_unix.go
@@ -0,0 +1,159 @@
+// Copyright 2009 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.
+
+// +build darwin freebsd linux openbsd
+
+package syscall
+
+import (
+ "sync"
+ "unsafe"
+)
+
+var (
+ Stdin = 0
+ Stdout = 1
+ Stderr = 2
+)
+
+func c_syscall32(trap int32, a1, a2, a3, a4, a5, a6 int32) int32 __asm__ ("syscall");
+func c_syscall64(trap int64, a1, a2, a3, a4, a5, a6 int64) int64 __asm__ ("syscall");
+
+// Do a system call. We look at the size of uintptr to see how to pass
+// the arguments, so that we don't pass a 64-bit value when the function
+// expects a 32-bit one.
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+ entersyscall()
+ var r uintptr
+ if unsafe.Sizeof(r) == 4 {
+ r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0)
+ r = uintptr(r1)
+ } else {
+ r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0)
+ r = uintptr(r1)
+ }
+ errno := GetErrno()
+ exitsyscall()
+ return r, 0, uintptr(errno)
+}
+
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+ entersyscall()
+ var r uintptr
+ if unsafe.Sizeof(r) == 4 {
+ r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3),
+ int32(a4), int32(a5), int32(a6))
+ r = uintptr(r1)
+ } else {
+ r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3),
+ int64(a4), int64(a5), int64(a6))
+ r = uintptr(r1)
+ }
+ errno := GetErrno()
+ exitsyscall()
+ return r, 0, uintptr(errno)
+}
+
+func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+ var r uintptr
+ if unsafe.Sizeof(r) == 4 {
+ r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0)
+ r = uintptr(r1)
+ } else {
+ r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0)
+ r = uintptr(r1)
+ }
+ errno := GetErrno()
+ return r, 0, uintptr(errno)
+}
+
+func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+ var r uintptr
+ if unsafe.Sizeof(r) == 4 {
+ r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3),
+ int32(a4), int32(a5), int32(a6))
+ r = uintptr(r1)
+ } else {
+ r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3),
+ int64(a4), int64(a5), int64(a6))
+ r = uintptr(r1)
+ }
+ errno := GetErrno()
+ return r, 0, uintptr(errno)
+}
+
+// Mmap manager, for use by operating system-specific implementations.
+// Gccgo only has one implementation but we do this to correspond to gc.
+
+type mmapper struct {
+ sync.Mutex
+ active map[*byte][]byte // active mappings; key is last byte in mapping
+ mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, int)
+ munmap func(addr uintptr, length uintptr) int
+}
+
+func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
+ if length <= 0 {
+ return nil, EINVAL
+ }
+
+ // Map the requested memory.
+ addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
+ if errno != 0 {
+ return nil, errno
+ }
+
+ // Slice memory layout
+ var sl = struct {
+ addr uintptr
+ len int
+ cap int
+ }{addr, length, length}
+
+ // Use unsafe to turn sl into a []byte.
+ b := *(*[]byte)(unsafe.Pointer(&sl))
+
+ // Register mapping in m and return it.
+ p := &b[cap(b)-1]
+ m.Lock()
+ defer m.Unlock()
+ m.active[p] = b
+ return b, 0
+}
+
+func (m *mmapper) Munmap(data []byte) (errno int) {
+ if len(data) == 0 || len(data) != cap(data) {
+ return EINVAL
+ }
+
+ // Find the base of the mapping.
+ p := &data[cap(data)-1]
+ m.Lock()
+ defer m.Unlock()
+ b := m.active[p]
+ if b == nil || &b[0] != &data[0] {
+ return EINVAL
+ }
+
+ // Unmap the memory and update m.
+ if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != 0 {
+ return errno
+ }
+ m.active[p] = nil, false
+ return 0
+}
+
+var mapper = &mmapper{
+ active: make(map[*byte][]byte),
+ mmap: mmap,
+ munmap: munmap,
+}
+
+func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
+ return mapper.Mmap(fd, offset, length, prot, flags)
+}
+
+func Munmap(b []byte) (errno int) {
+ return mapper.Munmap(b)
+}
diff --git a/libgo/go/syscall/wait.c b/libgo/go/syscall/wait.c
new file mode 100644
index 00000000000..cee84c9cb52
--- /dev/null
+++ b/libgo/go/syscall/wait.c
@@ -0,0 +1,107 @@
+/* wait.c -- functions for getting wait status values.
+
+ 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.
+
+ We use C code to extract the wait status so that we can easily be
+ OS-independent. */
+
+#define _GNU_SOURCE
+#define __EXTENSIONS__
+
+#include <stdint.h>
+#include <sys/wait.h>
+
+extern _Bool Exited (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.Exited.N32_libgo_syscall.syscall.WaitStatus");
+
+_Bool
+Exited (uint32_t *w)
+{
+ return WIFEXITED (*w) != 0;
+}
+
+extern _Bool Signaled (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.Signaled.N32_libgo_syscall.syscall.WaitStatus");
+
+_Bool
+Signaled (uint32_t *w)
+{
+ return WIFSIGNALED (*w) != 0;
+}
+
+extern _Bool Stopped (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.Stopped.N32_libgo_syscall.syscall.WaitStatus");
+
+_Bool
+Stopped (uint32_t *w)
+{
+ return WIFSTOPPED (*w) != 0;
+}
+
+extern _Bool Continued (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.Continued.N32_libgo_syscall.syscall.WaitStatus");
+
+_Bool
+Continued (uint32_t *w)
+{
+ return WIFCONTINUED (*w) != 0;
+}
+
+extern _Bool CoreDump (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.CoreDump.N32_libgo_syscall.syscall.WaitStatus");
+
+_Bool
+CoreDump (uint32_t *w)
+{
+ return WCOREDUMP (*w) != 0;
+}
+
+extern int ExitStatus (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.ExitStatus.N32_libgo_syscall.syscall.WaitStatus");
+
+int
+ExitStatus (uint32_t *w)
+{
+ if (!WIFEXITED (*w))
+ return -1;
+ return WEXITSTATUS (*w);
+}
+
+extern int Signal (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.Signal.N32_libgo_syscall.syscall.WaitStatus");
+
+int
+Signal (uint32_t *w)
+{
+ if (!WIFSIGNALED (*w))
+ return -1;
+ return WTERMSIG (*w);
+}
+
+extern int StopSignal (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.StopSignal.N32_libgo_syscall.syscall.WaitStatus");
+
+int
+StopSignal (uint32_t *w)
+{
+ if (!WIFSTOPPED (*w))
+ return -1;
+ return WSTOPSIG (*w);
+}
+
+extern int TrapCause (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.TrapCause.N32_libgo_syscall.syscall.WaitStatus");
+
+int
+TrapCause (uint32_t *w)
+{
+#ifndef __linux__
+ return -1;
+#else
+ if (!WIFSTOPPED (*w) || WSTOPSIG (*w) != SIGTRAP)
+ return -1;
+ return *w >> 16;
+#endif
+}