===================================================================
@@ -1,418 +0,0 @@
-// sysfile.go -- File 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.
-
-// Support for basic Unix file operations. This file simply
-// translates from Go data types to Unix data types, and handles
-// errno. FIXME: This could probably be done mechanically.
-
-package syscall
-
-import "unsafe"
-
-// FIXME.
-const OS = "linux"
-
-func libc_open(name *byte, mode int, perm int) int __asm__ ("open");
-func libc_close(fd int) int __asm__ ("close");
-func libc_read(fd int, buf *byte, count Size_t) Ssize_t __asm__ ("read");
-func libc_write(fd int, buf *byte, count Size_t) Ssize_t __asm__ ("write");
-func libc_pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pread64");
-func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pwrite64");
-func libc_lseek64(int, Offset_t, int) Offset_t __asm__ ("lseek64");
-func libc_pipe(filedes *int) int __asm__("pipe");
-func libc_stat(name *byte, buf *Stat_t) int __asm__ ("stat");
-func libc_fstat(fd int, buf *Stat_t) int __asm__ ("fstat");
-func libc_lstat(name *byte, buf *Stat_t) int __asm__ ("lstat");
-func libc_unlink(name *byte) int __asm__ ("unlink");
-func libc_rmdir(name *byte) int __asm__ ("rmdir");
-func libc_fcntl(fd int, cmd int, arg int) int __asm__ ("fcntl");
-func libc_mkdir(name *byte, perm Mode_t) int __asm__ ("mkdir");
-func libc_gettimeofday(tv *Timeval, tz *Timezone) int __asm__ ("gettimeofday");
-func libc_select(int, *byte, *byte, *byte, *Timeval) int __asm__ ("select");
-func libc_chdir(name *byte) int __asm__ ("chdir");
-func libc_fchdir(int) int __asm__ ("fchdir");
-func libc_getcwd(*byte, Size_t) *byte __asm__ ("getcwd");
-func libc_link(oldpath *byte, newpath *byte) int __asm__ ("link");
-func libc_symlink(oldpath *byte, newpath *byte) int __asm__ ("symlink");
-func libc_readlink(*byte, *byte, Size_t) Ssize_t __asm__ ("readlink");
-func libc_rename(oldpath *byte, newpath *byte) int __asm__ ("rename");
-func libc_chmod(path *byte, mode Mode_t) int __asm__ ("chmod");
-func libc_fchmod(fd int, mode Mode_t) int __asm__ ("fchmod");
-func libc_chown(path *byte, owner Uid_t, group Gid_t) int __asm__ ("chown");
-func libc_fchown(fd int, owner Uid_t, group Gid_t) int __asm__ ("fchown");
-func libc_lchown(path *byte, owner Uid_t, group Gid_t) int __asm__ ("lchown");
-func libc_truncate64(path *byte, length Offset_t) int __asm__ ("truncate64");
-func libc_ftruncate64(fd int, length Offset_t) int __asm__ ("ftruncate64");
-func libc_utimes(filename *byte, times *[2]Timeval) int __asm__ ("utimes");
-func libc_getuid() Uid_t __asm__ ("getuid");
-func libc_geteuid() Uid_t __asm__ ("geteuid");
-func libc_getgid() Gid_t __asm__ ("getgid");
-func libc_getegid() Gid_t __asm__ ("getegid");
-func libc_getgroups(size int, list *Gid_t) int __asm__ ("getgroups");
-func libc_setgroups(size Size_t, list *Gid_t) int __asm__ ("setgroups");
-func libc_getpagesize() int __asm__ ("getpagesize");
-func libc_exit(status int) __asm__ ("exit")
-func libc_getpid() Pid_t __asm__ ("getpid")
-func libc_getppid() Pid_t __asm__ ("getppid")
-func libc_kill(Pid_t, int) int __asm__ ("kill")
-
-func Open(name string, mode int, perm int) (fd int, errno int) {
- fd = libc_open(StringBytePtr(name), mode, perm);
- if fd < 0 { errno = GetErrno() }
- return;
-}
-
-func Creat(name string, perm int) (fd int, errno int) {
- fd = libc_open(StringBytePtr(name), O_CREAT | O_WRONLY | O_TRUNC, perm);
- if fd < 0 { errno = GetErrno() }
- return;
-}
-
-func Close(fd int) (errno int) {
- r := libc_close(fd);
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Read(fd int, p []byte) (n int, errno int) {
- var _p0 *byte;
- if len(p) > 0 { _p0 = &p[0]; }
- r := libc_read(fd, _p0, Size_t(len(p)));
- if r == -1 { errno = GetErrno() }
- n = int(r);
- return;
-}
-
-func Write(fd int, p []byte) (n int, errno int) {
- var _p0 *byte;
- if len(p) > 0 { _p0 = &p[0]; }
- r := libc_write(fd, _p0, Size_t(len(p)));
- if r == -1 { errno = GetErrno() }
- n = int(r);
- return;
-}
-
-func Pread(fd int, p []byte, offset int64) (n int, errno int) {
- var _p0 *byte;
- if len(p) > 0 { _p0 = &p[0]; }
- r := libc_pread(fd, _p0, Size_t(len(p)), Offset_t(offset));
- if r == -1 { errno = GetErrno() }
- n = int(r);
- return;
-}
-
-func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
- var _p0 *byte;
- if len(p) > 0 { _p0 = &p[0]; }
- r := libc_pwrite(fd, _p0, Size_t(len(p)), Offset_t(offset));
- if r == -1 { errno = GetErrno() }
- n = int(r);
- return;
-}
-
-func Seek(fd int, offset int64, whence int) (off int64, errno int) {
- r := libc_lseek64(fd, Offset_t(offset), whence);
- if r == -1 { errno = GetErrno() }
- off = int64(r);
- return;
-}
-
-func Pipe(p []int) (errno int) {
- if len(p) != 2 {
- return EINVAL;
- }
- var pp [2]int;
- r := libc_pipe(&pp[0]);
- if r < 0 {
- errno = GetErrno();
- }
- p[0] = pp[0];
- p[1] = pp[1];
- return;
-}
-
-func Stat(name string, buf *Stat_t) (errno int) {
- r := libc_stat(StringBytePtr(name), buf);
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Lstat(name string, buf *Stat_t) (errno int) {
- r := libc_lstat(StringBytePtr(name), buf);
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Fstat(fd int, buf *Stat_t) (errno int) {
- r := libc_fstat(fd, buf);
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Unlink(name string) (errno int) {
- r := libc_unlink(StringBytePtr(name));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Rmdir(name string) (errno int) {
- r := libc_rmdir(StringBytePtr(name));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Mkdir(path string, mode int) (errno int) {
- r := libc_mkdir(StringBytePtr(path), Mode_t(mode));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Gettimeofday(tv *Timeval) (errno int) {
- r := libc_gettimeofday(tv, nil);
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-type FdSet struct {
- __fds_bits [32]int32;
-}
-
-func Select(nfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, errno int) {
- n = libc_select(nfds, (*byte)(unsafe.Pointer(r)),
- (*byte)(unsafe.Pointer(e)),
- (*byte)(unsafe.Pointer(e)), timeout);
- if n < 0 { errno = GetErrno() }
- return;
-}
-
-func Chdir(path string) (errno int) {
- r := libc_chdir(StringBytePtr(path));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Fchdir(fd int) (errno int) {
- r := libc_fchdir(int(fd));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-const ImplementsGetwd = true
-
-func Getwd() (ret string, errno int) {
- for len := Size_t(4096); ; len *= 2 {
- b := make([]byte, len);
- p := libc_getcwd(&b[0], len);
- if p != nil {
- i := 0;
- for b[i] != 0 {
- i++;
- }
- return string(b[0:i]), 0;
- }
- e := GetErrno();
- if e != ERANGE {
- return "", e;
- }
- }
-}
-
-func Link(oldpath, newpath string) (errno int) {
- r := libc_link(StringBytePtr(oldpath), StringBytePtr(newpath));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Symlink(oldpath, newpath string) (errno int) {
- r := libc_symlink(StringBytePtr(oldpath), StringBytePtr(newpath));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Readlink(path string, buf []byte) (n int, errno int) {
- var _p0 *byte;
- if len(buf) > 0 { _p0 = &buf[0]; }
- r := libc_readlink(StringBytePtr(path), _p0, Size_t(len(buf)));
- if r < 0 { errno = GetErrno() }
- n = int(r);
- return;
-}
-
-func Rename(oldpath, newpath string) (errno int) {
- r := libc_rename(StringBytePtr(oldpath), StringBytePtr(newpath));
- if r < 0 { errno = GetErrno() }
- return
-}
-
-func Chmod(path string, mode int) (errno int) {
- r := libc_chmod(StringBytePtr(path), Mode_t(mode));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Fchmod(fd, mode int) (errno int) {
- r := libc_fchmod(fd, Mode_t(mode));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Chown(path string, uid int, gid int) (errno int) {
- r := libc_chown(StringBytePtr(path), Uid_t(uid), Gid_t(gid));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Lchown(path string, uid int, gid int) (errno int) {
- r := libc_lchown(StringBytePtr(path), Uid_t(uid), Gid_t(gid));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Fchown(fd int, uid int, gid int) (errno int) {
- r := libc_fchown(fd, Uid_t(uid), Gid_t(gid));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Truncate(path string, length int64) (errno int) {
- r := libc_truncate64(StringBytePtr(path), Offset_t(length));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Ftruncate(fd int, length int64) (errno int) {
- r := libc_ftruncate64(fd, Offset_t(length));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Utimes(path string, tv []Timeval) (errno int) {
- if len(tv) != 2 {
- return EINVAL;
- }
- r := libc_utimes(StringBytePtr(path),
- (*[2]Timeval)(unsafe.Pointer(&tv[0])));
- if r < 0 {
- errno = GetErrno();
- }
- return;
-}
-
-// Getuid returns the numeric user id of the caller.
-func Getuid() int {
- return int(libc_getuid());
-}
-
-// Geteuid returns the numeric effective user id of the caller.
-func Geteuid() int {
- return int(libc_geteuid());
-}
-
-// Getgid returns the numeric group id of the caller.
-func Getgid() int {
- return int(libc_getgid());
-}
-
-// Getegid returns the numeric effective group id of the caller.
-func Getegid() int {
- return int(libc_getegid());
-}
-
-// Getgroups returns a list of the numeric ids of groups that the caller belongs to.
-func Getgroups() (gids []int, errno int) {
- n := libc_getgroups(0, nil);
- if n < 0 {
- return nil, GetErrno();
- }
- 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 = libc_getgroups(n, &a[0]);
- if n < 0 {
- return nil, GetErrno();
- }
- gids = make([]int, n);
- for i, v := range a[0:n] {
- gids[i] = int(v);
- }
- return;
-}
-
-func Setgroups(gids []int) (errno int) {
- if len(gids) == 0 {
- return libc_setgroups(0, nil);
- }
-
- a := make([]Gid_t, len(gids));
- for i, v := range gids {
- a[i] = Gid_t(v);
- }
- return libc_setgroups(Size_t(len(a)), &a[0]);
-}
-
-func Getpagesize() int {
- return libc_getpagesize();
-}
-
-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;
-}
-
-func Exit(code int) {
- libc_exit(code);
-}
-
-func Sleep(nsec int64) (errno int) {
- tv := NsecToTimeval(nsec);
- n, err := Select(0, nil, nil, nil, &tv);
- return err;
-}
-
-func fcntl(fd, cmd, arg int) (val int, errno int) {
- val = libc_fcntl(int(fd), int(cmd), int(arg));
- if val == -1 { errno = GetErrno() }
- return;
-}
-
-func Getpid() (pid int) {
- return int(libc_getpid());
-}
-
-func Getppid() (ppid int) {
- return int(libc_getppid());
-}
-
-func Kill(pid int, sig int) (errno int) {
- r := libc_kill(Pid_t(pid), sig)
- if r < 0 {
- errno = GetErrno()
- }
- return
-}
===================================================================
@@ -0,0 +1,134 @@
+// 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.
+
+// Low-level socket interface.
+// Only for implementing net package.
+// DO NOT USE DIRECTLY.
+
+package syscall
+
+import "unsafe"
+
+type RawSockaddrInet4 struct {
+ Len uint8;
+ Family uint8;
+ Port uint16;
+ Addr [4]byte /* in_addr */;
+ Zero [8]uint8;
+}
+
+type RawSockaddrInet6 struct {
+ Len uint8;
+ Family uint8;
+ Port uint16;
+ Flowinfo uint32;
+ Addr [16]byte /* in6_addr */;
+ Scope_id uint32;
+}
+
+type RawSockaddrUnix struct {
+ Len uint8;
+ Family uint8;
+ Path [108]int8;
+}
+
+type RawSockaddr struct {
+ Len uint8;
+ Family uint8;
+ Data [14]int8;
+}
+
+func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+ if sa.Port < 0 || sa.Port > 0xFFFF {
+ return nil, 0, EINVAL;
+ }
+ sa.raw.Len = SizeofSockaddrInet4;
+ sa.raw.Family = AF_INET;
+ p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
+ p[0] = byte(sa.Port>>8);
+ p[1] = byte(sa.Port);
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.raw.Addr[i] = sa.Addr[i];
+ }
+ return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), Socklen_t(sa.raw.Len), 0;
+}
+
+func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+ if sa.Port < 0 || sa.Port > 0xFFFF {
+ return nil, 0, EINVAL;
+ }
+ sa.raw.Len = SizeofSockaddrInet6;
+ sa.raw.Family = AF_INET6;
+ p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
+ p[0] = byte(sa.Port>>8);
+ p[1] = byte(sa.Port);
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.raw.Addr[i] = sa.Addr[i];
+ }
+ return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), Socklen_t(sa.raw.Len), 0;
+}
+
+func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+ name := sa.Name;
+ n := len(name);
+ if n >= len(sa.raw.Path) || n == 0 {
+ return nil, 0, EINVAL;
+ }
+ sa.raw.Len = byte(3 + n); // 2 for Family, Len; 1 for NUL.
+ sa.raw.Family = AF_UNIX;
+ for i := 0; i < n; i++ {
+ sa.raw.Path[i] = int8(name[i]);
+ }
+ if sa.raw.Path[0] == '@' {
+ sa.raw.Path[0] = 0;
+ }
+
+ // length is family, name, NUL.
+ return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), Socklen_t(sa.raw.Len), 0;
+}
+
+func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
+ switch rsa.Addr.Family {
+ case AF_UNIX:
+ pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
+ if pp.Len < 3 || pp.Len > SizeofSockaddrUnix {
+ return nil, EINVAL
+ }
+ sa := new(SockaddrUnix)
+ n := int(pp.Len) - 3 // subtract leading Family, Len, terminating NUL.
+ for i := 0; i < n; i++ {
+ if pp.Path[i] == 0 {
+ // found early NUL; assume Len is overestimating.
+ n = i
+ break
+ }
+ }
+ bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))
+ sa.Name = string(bytes[0:n])
+ return sa, 0
+
+ case AF_INET:
+ pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
+ sa := new(SockaddrInet4);
+ p := (*[2]byte)(unsafe.Pointer(&pp.Port));
+ sa.Port = int(p[0])<<8 + int(p[1]);
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.Addr[i] = pp.Addr[i];
+ }
+ return sa, 0;
+
+ case AF_INET6:
+ pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
+ sa := new(SockaddrInet6);
+ p := (*[2]byte)(unsafe.Pointer(&pp.Port));
+ sa.Port = int(p[0])<<8 + int(p[1]);
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.Addr[i] = pp.Addr[i];
+ }
+ return sa, 0;
+ }
+ return nil, EAFNOSUPPORT;
+}
===================================================================
@@ -8,57 +8,7 @@
package syscall
-import (
- "sync";
- "unsafe";
-)
-
-// 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).
+import "unsafe"
func libc_fcntl(fd int, cmd int, arg int) int __asm__ ("fcntl")
func libc_fork() Pid_t __asm__ ("fork")
@@ -68,40 +18,6 @@ func libc_execve(*byte, **byte, **byte)
func libc_sysexit(int) __asm__ ("_exit")
func libc_wait4(Pid_t, *int, int, *Rusage) Pid_t __asm__ ("wait4")
-type WaitStatus int
-
-var ForkLock sync.RWMutex
-
-// Convert array of string to array
-// of NUL-terminated byte pointer.
-func StringArrayPtr(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;
- }
- flag, 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.)
@@ -318,71 +234,6 @@ func Exec(argv0 string, argv []string, e
return GetErrno();
}
-// Wait status is 7 bits at bottom, either 0 (exited),
-// 0x7F (stopped), or a signal number that caused an exit.
-// The 0x80 bit is whether there was a core dump.
-// An extra number (exit code, signal causing a stop)
-// is in the high bits. At least that's the idea.
-// There are various irregularities. For example, the
-// "continued" status is 0xFFFF, distinguishing itself
-// from stopped via the core dump bit.
-
-const (
- mask = 0x7F;
- core = 0x80;
- exited = 0x00;
- stopped = 0x7F;
- shift = 8;
-)
-
-func (w WaitStatus) Exited() bool {
- return w&mask == exited;
-}
-
-func (w WaitStatus) Signaled() bool {
- return w&mask != stopped && w&mask != exited;
-}
-
-func (w WaitStatus) Stopped() bool {
- return w&0xFF == stopped;
-}
-
-func (w WaitStatus) Continued() bool {
- return w == 0xFFFF;
-}
-
-func (w WaitStatus) CoreDump() bool {
- return w.Signaled() && w&core != 0;
-}
-
-func (w WaitStatus) ExitStatus() int {
- if !w.Exited() {
- return -1;
- }
- return int(w >> shift) & 0xFF;
-}
-
-func (w WaitStatus) Signal() int {
- if !w.Signaled() {
- return -1;
- }
- return int(w & mask);
-}
-
-func (w WaitStatus) StopSignal() int {
- if !w.Stopped() {
- return -1;
- }
- return int(w >> shift) & 0xFF;
-}
-
-func (w WaitStatus) TrapCause() int {
- if w.StopSignal() != SIGTRAP {
- return -1;
- }
- return int(w >> shift) >> 8;
-}
-
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
var status int;
r := libc_wait4(Pid_t(pid), &status, options, rusage);
===================================================================
@@ -12,38 +12,15 @@ package syscall
import "unsafe"
-type RawSockaddrInet4 struct {
- Family uint16;
- Port uint16;
- Addr [4]byte /* in_addr */;
- Zero [8]uint8;
-}
const SizeofSockaddrInet4 = 16
-
-type RawSockaddrInet6 struct {
- Family uint16;
- Port uint16;
- Flowinfo uint32;
- Addr [16]byte /* in6_addr */;
- Scope_id uint32;
-}
const SizeofSockaddrInet6 = 28
-
-type RawSockaddrUnix struct {
- Family uint16;
- Path [108]int8;
-}
const SizeofSockaddrUnix = 110
-type RawSockaddr struct {
- Family uint16;
- Data [14]int8;
-}
-
type RawSockaddrAny struct {
Addr RawSockaddr;
Pad [12]int8;
}
+
const SizeofSockaddrAny = 0x1c;
// For testing: clients can set this flag to force
@@ -60,113 +37,17 @@ type SockaddrInet4 struct {
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;
- p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
- p[0] = byte(sa.Port>>8);
- p[1] = byte(sa.Port);
- for i := 0; i < len(sa.Addr); i++ {
- sa.raw.Addr[i] = sa.Addr[i];
- }
- return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet4, 0;
-}
-
type SockaddrInet6 struct {
Port int;
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;
- p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
- p[0] = byte(sa.Port>>8);
- p[1] = byte(sa.Port);
- for i := 0; i < len(sa.Addr); i++ {
- sa.raw.Addr[i] = sa.Addr[i];
- }
- return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet6, 0;
-}
-
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;
- for i := 0; i < n; i++ {
- sa.raw.Path[i] = int8(name[i]);
- }
- if sa.raw.Path[0] == '@' {
- sa.raw.Path[0] = 0;
- }
-
- // length is family, name, NUL.
- return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), 1 + Socklen_t(n) + 1, 0;
-}
-
-func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
- switch rsa.Addr.Family {
- case AF_UNIX:
- pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa));
- sa := new(SockaddrUnix);
- if pp.Path[0] == 0 {
- // "Abstract" Unix domain socket.
- // Rewrite leading NUL as @ for textual display.
- // (This is the standard convention.)
- // Not friendly to overwrite in place,
- // but the callers below don't care.
- pp.Path[0] = '@';
- }
-
- // Assume path ends at NUL.
- // This is not technically the Linux semantics for
- // abstract Unix domain sockets--they are supposed
- // to be uninterpreted fixed-size binary blobs--but
- // everyone uses this convention.
- n := 0;
- for n < len(pp.Path) && pp.Path[n] != 0 {
- n++;
- }
- bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]));
- sa.Name = string(bytes[0:n]);
- return sa, 0;
-
- case AF_INET:
- pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
- sa := new(SockaddrInet4);
- p := (*[2]byte)(unsafe.Pointer(&pp.Port));
- sa.Port = int(p[0])<<8 + int(p[1]);
- for i := 0; i < len(sa.Addr); i++ {
- sa.Addr[i] = pp.Addr[i];
- }
- return sa, 0;
-
- case AF_INET6:
- pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
- sa := new(SockaddrInet6);
- p := (*[2]byte)(unsafe.Pointer(&pp.Port));
- sa.Port = int(p[0])<<8 + int(p[1]);
- for i := 0; i < len(sa.Addr); i++ {
- sa.Addr[i] = pp.Addr[i];
- }
- return sa, 0;
- }
- return nil, EAFNOSUPPORT;
-}
-
type Linger struct {
Onoff int32;
Linger int32;
===================================================================
@@ -0,0 +1,34 @@
+// sysfile_rtems.go -- RTEMS specific file handling.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Support for basic Unix file operations. This file simply
+// translates from Go data types to Unix data types, and handles
+// errno. FIXME: This could probably be done mechanically.
+
+package syscall
+
+const (
+ OS = "rtems"
+ // No support for async I/O in RTEMS.
+ O_ASYNC = 0
+)
+
+func libc_pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pread")
+func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pwrite")
+func libc_lseek64(int, Offset_t, int) Offset_t __asm__ ("lseek")
+func libc_truncate64(path *byte, length Offset_t) int __asm__ ("truncate")
+func libc_ftruncate64(fd int, length Offset_t) int __asm__ ("ftruncate")
+func libc_nanosleep(req *Timespec, rem *Timespec) int __asm__ ("nanosleep")
+
+func Sleep(nsec int64) (errno int) {
+ errno = 0
+ ts := NsecToTimespec(nsec)
+ r := libc_nanosleep(&ts, nil)
+ if r < 0 {
+ errno = GetErrno()
+ }
+ return
+}
===================================================================
@@ -0,0 +1,24 @@
+// stringbyte.go -- string to bytes functions.
+
+// 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
+
+// StringByteSlice returns a NUL-terminated slice of bytes
+// containing the text of s.
+func StringByteSlice(s string) []byte {
+ a := make([]byte, len(s)+1);
+ for i := 0; i < len(s); i++ {
+ a[i] = s[i];
+ }
+ return a;
+}
+
+// StringBytePtr returns a pointer to a NUL-terminated array of bytes
+// containing the text of s.
+func StringBytePtr(s string) *byte {
+ p := StringByteSlice(s);
+ return &p[0];
+}
===================================================================
@@ -0,0 +1,33 @@
+// syscall_stubs.go -- Stubs of the basic syscall interface.
+
+// 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.
+
+// This package 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 are stubs.
+
+package syscall
+
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+ var r uintptr;
+ var i int;
+ i = -1;
+ r = uintptr(i);
+ return r, 0, uintptr(ENOSYS);
+}
+
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+ var r uintptr;
+ var i int;
+ i = -1;
+ r = uintptr(i);
+ return r, 0, uintptr(ENOSYS);
+}
===================================================================
@@ -0,0 +1,33 @@
+// 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
+
+const ENONE = 0
+
+// RTEMS uses strerror_r in newlib, which is a GNU extension returning a char *.
+func libc_strerror_r(int, *byte, Size_t) int __asm__ ("strerror_r")
+func GetErrno() int
+func SetErrno(int)
+
+func Errstr(errno int) string {
+ for len := Size_t(128); ; len *= 2 {
+ b := make([]byte, len+1)
+
+ // The newlib strerror_r always returns the string in buffer.
+ libc_strerror_r(errno, &b[0], len)
+ b[len] = 0
+
+ i := 0
+ for b[i] != 0 {
+ i++
+ }
+
+ if Size_t(i) < len {
+ return string(b[0:i])
+ }
+ }
+}
===================================================================
@@ -0,0 +1,38 @@
+// sysfile_linux.go -- Linux specific file handling.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Support for basic Unix file operations. This file simply
+// translates from Go data types to Unix data types, and handles
+// errno. FIXME: This could probably be done mechanically.
+
+package syscall
+
+const OS = "linux"
+
+func libc_pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pread64")
+func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pwrite64")
+func libc_lseek64(int, Offset_t, int) Offset_t __asm__ ("lseek64")
+func libc_truncate64(path *byte, length Offset_t) int __asm__ ("truncate64")
+func libc_ftruncate64(fd int, length Offset_t) int __asm__ ("ftruncate64")
+func libc_setgroups(size Size_t, list *Gid_t) int __asm__ ("setgroups")
+
+func Sleep(nsec int64) (errno int) {
+ tv := NsecToTimeval(nsec);
+ n, err := Select(0, nil, nil, nil, &tv);
+ return err;
+}
+
+func Setgroups(gids []int) (errno int) {
+ if len(gids) == 0 {
+ return libc_setgroups(0, nil);
+ }
+
+ a := make([]Gid_t, len(gids));
+ for i, v := range gids {
+ a[i] = Gid_t(v);
+ }
+ return libc_setgroups(Size_t(len(a)), &a[0]);
+}
===================================================================
@@ -0,0 +1,413 @@
+// sysfile_posix.go -- POSIX File handling.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Support for basic Unix file operations. This file simply
+// translates from Go data types to Unix data types, and handles
+// errno. FIXME: This could probably be done mechanically.
+
+package syscall
+
+import "unsafe"
+
+func libc_open(name *byte, mode int, perm int) int __asm__ ("open");
+func libc_close(fd int) int __asm__ ("close");
+func libc_read(fd int, buf *byte, count Size_t) Ssize_t __asm__ ("read");
+func libc_write(fd int, buf *byte, count Size_t) Ssize_t __asm__ ("write");
+func libc_pipe(filedes *int) int __asm__("pipe");
+func libc_stat(name *byte, buf *Stat_t) int __asm__ ("stat");
+func libc_fstat(fd int, buf *Stat_t) int __asm__ ("fstat");
+func libc_lstat(name *byte, buf *Stat_t) int __asm__ ("lstat");
+func libc_unlink(name *byte) int __asm__ ("unlink");
+func libc_rmdir(name *byte) int __asm__ ("rmdir");
+func libc_fcntl(fd int, cmd int, arg int) int __asm__ ("fcntl");
+func libc_mkdir(name *byte, perm Mode_t) int __asm__ ("mkdir");
+func libc_gettimeofday(tv *Timeval, tz *Timezone) int __asm__ ("gettimeofday");
+func libc_select(int, *byte, *byte, *byte, *Timeval) int __asm__ ("select");
+func libc_chdir(name *byte) int __asm__ ("chdir");
+func libc_fchdir(int) int __asm__ ("fchdir");
+func libc_getcwd(*byte, Size_t) *byte __asm__ ("getcwd");
+func libc_link(oldpath *byte, newpath *byte) int __asm__ ("link");
+func libc_symlink(oldpath *byte, newpath *byte) int __asm__ ("symlink");
+func libc_readlink(*byte, *byte, Size_t) Ssize_t __asm__ ("readlink");
+func libc_rename(oldpath *byte, newpath *byte) int __asm__ ("rename");
+func libc_chmod(path *byte, mode Mode_t) int __asm__ ("chmod");
+func libc_fchmod(fd int, mode Mode_t) int __asm__ ("fchmod");
+func libc_chown(path *byte, owner Uid_t, group Gid_t) int __asm__ ("chown");
+func libc_fchown(fd int, owner Uid_t, group Gid_t) int __asm__ ("fchown");
+func libc_lchown(path *byte, owner Uid_t, group Gid_t) int __asm__ ("lchown");
+func libc_utimes(filename *byte, times *[2]Timeval) int __asm__ ("utimes");
+func libc_getuid() Uid_t __asm__ ("getuid");
+func libc_geteuid() Uid_t __asm__ ("geteuid");
+func libc_getgid() Gid_t __asm__ ("getgid");
+func libc_getegid() Gid_t __asm__ ("getegid");
+func libc_getgroups(size int, list *Gid_t) int __asm__ ("getgroups");
+func libc_getpagesize() int __asm__ ("getpagesize");
+func libc_exit(status int) __asm__ ("exit")
+func libc_getpid() Pid_t __asm__ ("getpid")
+func libc_getppid() Pid_t __asm__ ("getppid")
+func libc_kill(Pid_t, int) int __asm__ ("kill")
+
+func Open(name string, mode int, perm int) (fd int, errno int) {
+ fd = libc_open(StringBytePtr(name), mode, perm);
+ if fd < 0 { errno = GetErrno() }
+ return;
+}
+
+func Creat(name string, perm int) (fd int, errno int) {
+ fd = libc_open(StringBytePtr(name), O_CREAT | O_WRONLY | O_TRUNC, perm);
+ if fd < 0 { errno = GetErrno() }
+ return;
+}
+
+func Close(fd int) (errno int) {
+ r := libc_close(fd);
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Read(fd int, p []byte) (n int, errno int) {
+ var _p0 *byte;
+ if len(p) > 0 { _p0 = &p[0]; }
+ r := libc_read(fd, _p0, Size_t(len(p)));
+ if r == -1 { errno = GetErrno() }
+ n = int(r);
+ return;
+}
+
+func Write(fd int, p []byte) (n int, errno int) {
+ var _p0 *byte;
+ if len(p) > 0 { _p0 = &p[0]; }
+ r := libc_write(fd, _p0, Size_t(len(p)));
+ if r == -1 { errno = GetErrno() }
+ n = int(r);
+ return;
+}
+
+func Pread(fd int, p []byte, offset int64) (n int, errno int) {
+ var _p0 *byte;
+ if len(p) > 0 { _p0 = &p[0]; }
+ r := libc_pread(fd, _p0, Size_t(len(p)), Offset_t(offset));
+ if r == -1 { errno = GetErrno() }
+ n = int(r);
+ return;
+}
+
+func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
+ var _p0 *byte;
+ if len(p) > 0 { _p0 = &p[0]; }
+ r := libc_pwrite(fd, _p0, Size_t(len(p)), Offset_t(offset));
+ if r == -1 { errno = GetErrno() }
+ n = int(r);
+ return;
+}
+
+func Seek(fd int, offset int64, whence int) (off int64, errno int) {
+ r := libc_lseek64(fd, Offset_t(offset), whence);
+ if r == -1 { errno = GetErrno() }
+ off = int64(r);
+ return;
+}
+
+func Pipe(p []int) (errno int) {
+ if len(p) != 2 {
+ return EINVAL;
+ }
+ var pp [2]int;
+ r := libc_pipe(&pp[0]);
+ if r < 0 {
+ errno = GetErrno();
+ }
+ p[0] = pp[0];
+ p[1] = pp[1];
+ return;
+}
+
+func Stat(name string, buf *Stat_t) (errno int) {
+ r := libc_stat(StringBytePtr(name), buf);
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Lstat(name string, buf *Stat_t) (errno int) {
+ r := libc_lstat(StringBytePtr(name), buf);
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Fstat(fd int, buf *Stat_t) (errno int) {
+ r := libc_fstat(fd, buf);
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Unlink(name string) (errno int) {
+ r := libc_unlink(StringBytePtr(name));
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Rmdir(name string) (errno int) {
+ r := libc_rmdir(StringBytePtr(name));
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Mkdir(path string, mode int) (errno int) {
+ r := libc_mkdir(StringBytePtr(path), Mode_t(mode));
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Gettimeofday(tv *Timeval) (errno int) {
+ r := libc_gettimeofday(tv, nil);
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+type FdSet_t struct {
+ Fds_bits [(FD_SETSIZE + 63) / 64]int64;
+}
+
+func FDSet(fd int, set *FdSet_t) {
+ set.Fds_bits[fd / 64] |= (1 << (uint)(fd % 64))
+}
+
+func FDClr(fd int, set *FdSet_t) {
+ set.Fds_bits[fd / 64] &= ^(1 << (uint)(fd % 64))
+}
+
+func FDIsSet(fd int, set *FdSet_t) bool {
+ if set.Fds_bits[fd / 64] & (1 << (uint)(fd % 64)) != 0 {
+ return true
+ } else {
+ return false
+ }
+}
+
+func FDZero(set *FdSet_t) {
+ for i := 0; i < ((FD_SETSIZE + 63) / 64); i++ {
+ set.Fds_bits[i] = 0
+ }
+}
+
+func Select(nfds int, r *FdSet_t, w *FdSet_t, e *FdSet_t, timeout *Timeval) (n int, errno int) {
+ n = libc_select(nfds, (*byte)(unsafe.Pointer(r)),
+ (*byte)(unsafe.Pointer(e)),
+ (*byte)(unsafe.Pointer(e)), timeout);
+ if n < 0 { errno = GetErrno() }
+ return;
+}
+
+func Chdir(path string) (errno int) {
+ r := libc_chdir(StringBytePtr(path));
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Fchdir(fd int) (errno int) {
+ r := libc_fchdir(int(fd));
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+const ImplementsGetwd = true
+
+func Getwd() (ret string, errno int) {
+ for len := Size_t(4096); ; len *= 2 {
+ b := make([]byte, len);
+ p := libc_getcwd(&b[0], len);
+ if p != nil {
+ i := 0;
+ for b[i] != 0 {
+ i++;
+ }
+ return string(b[0:i]), 0;
+ }
+ e := GetErrno();
+ if e != ERANGE {
+ return "", e;
+ }
+ }
+}
+
+func Link(oldpath, newpath string) (errno int) {
+ r := libc_link(StringBytePtr(oldpath), StringBytePtr(newpath));
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Symlink(oldpath, newpath string) (errno int) {
+ r := libc_symlink(StringBytePtr(oldpath), StringBytePtr(newpath));
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Readlink(path string, buf []byte) (n int, errno int) {
+ var _p0 *byte;
+ if len(buf) > 0 { _p0 = &buf[0]; }
+ r := libc_readlink(StringBytePtr(path), _p0, Size_t(len(buf)));
+ if r < 0 { errno = GetErrno() }
+ n = int(r);
+ return;
+}
+
+func Rename(oldpath, newpath string) (errno int) {
+ r := libc_rename(StringBytePtr(oldpath), StringBytePtr(newpath));
+ if r < 0 { errno = GetErrno() }
+ return
+}
+
+func Chmod(path string, mode int) (errno int) {
+ r := libc_chmod(StringBytePtr(path), Mode_t(mode));
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Fchmod(fd, mode int) (errno int) {
+ r := libc_fchmod(fd, Mode_t(mode));
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Chown(path string, uid int, gid int) (errno int) {
+ r := libc_chown(StringBytePtr(path), Uid_t(uid), Gid_t(gid));
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Lchown(path string, uid int, gid int) (errno int) {
+ r := libc_lchown(StringBytePtr(path), Uid_t(uid), Gid_t(gid));
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Fchown(fd int, uid int, gid int) (errno int) {
+ r := libc_fchown(fd, Uid_t(uid), Gid_t(gid));
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Truncate(path string, length int64) (errno int) {
+ r := libc_truncate64(StringBytePtr(path), Offset_t(length));
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Ftruncate(fd int, length int64) (errno int) {
+ r := libc_ftruncate64(fd, Offset_t(length));
+ if r < 0 { errno = GetErrno() }
+ return;
+}
+
+func Utimes(path string, tv []Timeval) (errno int) {
+ if len(tv) != 2 {
+ return EINVAL;
+ }
+ r := libc_utimes(StringBytePtr(path),
+ (*[2]Timeval)(unsafe.Pointer(&tv[0])));
+ if r < 0 {
+ errno = GetErrno();
+ }
+ return;
+}
+
+// Getuid returns the numeric user id of the caller.
+func Getuid() int {
+ return int(libc_getuid());
+}
+
+// Geteuid returns the numeric effective user id of the caller.
+func Geteuid() int {
+ return int(libc_geteuid());
+}
+
+// Getgid returns the numeric group id of the caller.
+func Getgid() int {
+ return int(libc_getgid());
+}
+
+// Getegid returns the numeric effective group id of the caller.
+func Getegid() int {
+ return int(libc_getegid());
+}
+
+// Getgroups returns a list of the numeric ids of groups that the caller belongs to.
+func Getgroups() (gids []int, errno int) {
+ n := libc_getgroups(0, nil);
+ if n < 0 {
+ return nil, GetErrno();
+ }
+ 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 = libc_getgroups(n, &a[0]);
+ if n < 0 {
+ return nil, GetErrno();
+ }
+ gids = make([]int, n);
+ for i, v := range a[0:n] {
+ gids[i] = int(v);
+ }
+ return;
+}
+
+func Getpagesize() int {
+ return libc_getpagesize();
+}
+
+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;
+}
+
+func Exit(code int) {
+ libc_exit(code);
+}
+
+func fcntl(fd, cmd, arg int) (val int, errno int) {
+ val = libc_fcntl(int(fd), int(cmd), int(arg));
+ if val == -1 { errno = GetErrno() }
+ return;
+}
+
+func Getpid() (pid int) {
+ return int(libc_getpid());
+}
+
+func Getppid() (ppid int) {
+ return int(libc_getppid());
+}
+
+func Kill(pid int, sig int) (errno int) {
+ r := libc_kill(Pid_t(pid), sig)
+ if r < 0 {
+ errno = GetErrno()
+ }
+ return
+}
===================================================================
@@ -0,0 +1,25 @@
+// exec_stubs.go -- fork/exec stubs.
+
+// 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 PtraceForkExec(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;
+}
===================================================================
@@ -0,0 +1,154 @@
+// exec_helpers.go -- helper functions used with fork, exec, wait.
+
+// 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 "sync"
+
+// 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).
+
+type WaitStatus int
+
+var ForkLock sync.RWMutex
+
+// Convert array of string to array
+// of NUL-terminated byte pointer.
+func StringArrayPtr(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;
+ }
+ flag, err = fcntl(fd, F_SETFL, flag);
+ return err;
+}
+
+// Wait status is 7 bits at bottom, either 0 (exited),
+// 0x7F (stopped), or a signal number that caused an exit.
+// The 0x80 bit is whether there was a core dump.
+// An extra number (exit code, signal causing a stop)
+// is in the high bits. At least that's the idea.
+// There are various irregularities. For example, the
+// "continued" status is 0xFFFF, distinguishing itself
+// from stopped via the core dump bit.
+
+const (
+ mask = 0x7F;
+ core = 0x80;
+ exited = 0x00;
+ stopped = 0x7F;
+ shift = 8;
+)
+
+func (w WaitStatus) Exited() bool {
+ return w&mask == exited;
+}
+
+func (w WaitStatus) Signaled() bool {
+ return w&mask != stopped && w&mask != exited;
+}
+
+func (w WaitStatus) Stopped() bool {
+ return w&0xFF == stopped;
+}
+
+func (w WaitStatus) Continued() bool {
+ return w == 0xFFFF;
+}
+
+func (w WaitStatus) CoreDump() bool {
+ return w.Signaled() && w&core != 0;
+}
+
+func (w WaitStatus) ExitStatus() int {
+ if !w.Exited() {
+ return -1;
+ }
+ return int(w >> shift) & 0xFF;
+}
+
+func (w WaitStatus) Signal() int {
+ if !w.Signaled() {
+ return -1;
+ }
+ return int(w & mask);
+}
+
+func (w WaitStatus) StopSignal() int {
+ if !w.Stopped() {
+ return -1;
+ }
+ return int(w >> shift) & 0xFF;
+}
+
+func (w WaitStatus) TrapCause() int {
+ if w.StopSignal() != SIGTRAP {
+ return -1;
+ }
+ return int(w >> shift) >> 8;
+}
===================================================================
@@ -0,0 +1,135 @@
+// 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.
+
+// Low-level socket interface.
+// Only for implementing net package.
+
+// DO NOT USE DIRECTLY.
+
+package syscall
+
+import "unsafe"
+
+type RawSockaddrInet4 struct {
+ Family uint16;
+ Port uint16;
+ Addr [4]byte /* in_addr */;
+ Zero [8]uint8;
+}
+
+type RawSockaddrInet6 struct {
+ Family uint16;
+ Port uint16;
+ Flowinfo uint32;
+ Addr [16]byte /* in6_addr */;
+ Scope_id uint32;
+}
+
+type RawSockaddrUnix struct {
+ Family uint16;
+ Path [108]int8;
+}
+
+type RawSockaddr struct {
+ Family uint16;
+ Data [14]int8;
+}
+
+func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+ if sa.Port < 0 || sa.Port > 0xFFFF {
+ return nil, 0, EINVAL;
+ }
+ sa.raw.Family = AF_INET;
+ p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
+ p[0] = byte(sa.Port>>8);
+ p[1] = byte(sa.Port);
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.raw.Addr[i] = sa.Addr[i];
+ }
+ return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet4, 0;
+}
+
+func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+ if sa.Port < 0 || sa.Port > 0xFFFF {
+ return nil, 0, EINVAL;
+ }
+ sa.raw.Family = AF_INET6;
+ p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
+ p[0] = byte(sa.Port>>8);
+ p[1] = byte(sa.Port);
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.raw.Addr[i] = sa.Addr[i];
+ }
+ return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet6, 0;
+}
+
+func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+ name := sa.Name;
+ n := len(name);
+ if n >= len(sa.raw.Path) || n == 0 {
+ return nil, 0, EINVAL;
+ }
+ sa.raw.Family = AF_UNIX;
+ for i := 0; i < n; i++ {
+ sa.raw.Path[i] = int8(name[i]);
+ }
+ if sa.raw.Path[0] == '@' {
+ sa.raw.Path[0] = 0;
+ }
+
+ // length is family, name, NUL.
+ return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), 1 + Socklen_t(n) + 1, 0;
+}
+
+func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
+ switch rsa.Addr.Family {
+ case AF_UNIX:
+ pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa));
+ sa := new(SockaddrUnix);
+ if pp.Path[0] == 0 {
+ // "Abstract" Unix domain socket.
+ // Rewrite leading NUL as @ for textual display.
+ // (This is the standard convention.)
+ // Not friendly to overwrite in place,
+ // but the callers below don't care.
+ pp.Path[0] = '@';
+ }
+
+ // Assume path ends at NUL.
+ // This is not technically the Linux semantics for
+ // abstract Unix domain sockets--they are supposed
+ // to be uninterpreted fixed-size binary blobs--but
+ // everyone uses this convention.
+ n := 0;
+ for n < len(pp.Path) - 3 && pp.Path[n] != 0 {
+ n++;
+ }
+ bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]));
+ sa.Name = string(bytes[0:n]);
+ return sa, 0;
+
+ case AF_INET:
+ pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
+ sa := new(SockaddrInet4);
+ p := (*[2]byte)(unsafe.Pointer(&pp.Port));
+ sa.Port = int(p[0])<<8 + int(p[1]);
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.Addr[i] = pp.Addr[i];
+ }
+ return sa, 0;
+
+ case AF_INET6:
+ pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
+ sa := new(SockaddrInet6);
+ p := (*[2]byte)(unsafe.Pointer(&pp.Port));
+ sa.Port = int(p[0])<<8 + int(p[1]);
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.Addr[i] = pp.Addr[i];
+ }
+ return sa, 0;
+ }
+ return nil, EAFNOSUPPORT;
+}
===================================================================
@@ -48,20 +48,3 @@ func Syscall6(trap, a1, a2, a3, a4, a5,
}
return r, 0, uintptr(GetErrno());
}
-
-// StringByteSlice returns a NUL-terminated slice of bytes
-// containing the text of s.
-func StringByteSlice(s string) []byte {
- a := make([]byte, len(s)+1);
- for i := 0; i < len(s); i++ {
- a[i] = s[i];
- }
- return a;
-}
-
-// StringBytePtr returns a pointer to a NUL-terminated array of bytes
-// containing the text of s.
-func StringBytePtr(s string) *byte {
- p := StringByteSlice(s);
- return &p[0];
-}
===================================================================
@@ -115,14 +115,17 @@ AC_SUBST(LIBFFIINCS)
is_darwin=no
is_freebsd=no
is_linux=no
+is_rtems=no
case ${host} in
*-*-darwin*) is_darwin=yes ;;
*-*-freebsd*) is_freebsd=yes ;;
*-*-linux*) is_linux=yes ;;
+ *-*-rtems*) is_rtems=yes ;;
esac
AM_CONDITIONAL(LIBGO_IS_DARWIN, test $is_darwin = yes)
AM_CONDITIONAL(LIBGO_IS_FREEBSD, test $is_freebsd = yes)
AM_CONDITIONAL(LIBGO_IS_LINUX, test $is_linux = yes)
+AM_CONDITIONAL(LIBGO_IS_RTEMS, test $is_rtems = yes)
is_386=no
is_x86_64=no
===================================================================
@@ -879,15 +879,35 @@ syscall_os_file =
syscall_arch_file =
endif
+if LIBGO_IS_RTEMS
+syscall_exec_os_file = syscalls/exec_stubs.go
+syscall_socket_os_file = syscalls/socket_bsd.go
+syscall_socket_epoll_file=
+syscall_sysfile_os_file = syscalls/sysfile_rtems.go
+syscall_syscall_file = syscalls/syscall_stubs.go
+syscall_errstr_file = syscalls/errstr_rtems.go
+else
+syscall_exec_os_file = syscalls/exec.go
+syscall_socket_os_file = syscalls/socket_linux.go
+syscall_socket_epoll_file = syscalls/socket_epoll.go
+syscall_sysfile_os_file = syscalls/sysfile_linux.go
+syscall_syscall_file = syscalls/syscall.go
+syscall_errstr_file = syscalls/errstr.go
+endif
+
go_syscall_files = \
- syscalls/errstr.go \
- syscalls/exec.go \
+ $(syscall_errstr_file) \
+ syscalls/exec_helpers.go \
+ $(syscall_exec_os_file) \
syscalls/socket.go \
- syscalls/socket_epoll.go \
- syscalls/syscall.go \
+ $(syscall_socket_os_file) \
+ $(syscall_socket_epoll_file) \
+ $(syscall_syscall_file) \
+ syscalls/stringbyte.go \
$(syscall_os_file) \
$(syscall_arch_file) \
- syscalls/sysfile.go \
+ syscalls/sysfile_posix.go \
+ $(syscall_sysfile_os_file) \
sysinfo.go
go_syscall_c_files = \
syscalls/errno.c