]> Cypherpunks repositories - gostls13.git/commitdiff
new syscall package: manually maintained files and scripts.
authorRuss Cox <rsc@golang.org>
Tue, 2 Jun 2009 05:14:57 +0000 (22:14 -0700)
committerRuss Cox <rsc@golang.org>
Tue, 2 Jun 2009 05:14:57 +0000 (22:14 -0700)
auto-generated files and deletions are in another CL.

goals for new syscall:
* automate as much as possible
* do not let clients do unsafe things
* use simple types (int not int64)
* fewer files

the files are renamed from foo_amd64_linux to foo_linux_amd64,
both because it reads better (all the linux are related, all the amd64 less so)
and because it made it easier to replace the existing ones.

R=r
DELTA=2336  (2260 added, 6 deleted, 70 changed)
OCL=29709
CL=29723

15 files changed:
src/lib/syscall/PORT [new file with mode: 0755]
src/lib/syscall/errstr.go [new file with mode: 0644]
src/lib/syscall/exec.go
src/lib/syscall/mkerrors [new file with mode: 0755]
src/lib/syscall/mksyscall [new file with mode: 0755]
src/lib/syscall/mksysnum_darwin [new file with mode: 0755]
src/lib/syscall/syscall.go
src/lib/syscall/syscall_darwin.go [new file with mode: 0644]
src/lib/syscall/syscall_darwin_amd64.go [new file with mode: 0644]
src/lib/syscall/syscall_linux.go [new file with mode: 0644]
src/lib/syscall/syscall_linux_amd64.go [new file with mode: 0644]
src/lib/syscall/types_darwin.c [new file with mode: 0644]
src/lib/syscall/types_darwin_amd64.c [new file with mode: 0644]
src/lib/syscall/types_linux.c [new file with mode: 0644]
src/lib/syscall/types_linux_amd64.c [new file with mode: 0644]

diff --git a/src/lib/syscall/PORT b/src/lib/syscall/PORT
new file mode 100755 (executable)
index 0000000..2f0fe14
--- /dev/null
@@ -0,0 +1,120 @@
+#!/bin/sh
+# 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.
+
+# The syscall package provides access to the raw system call
+# interface of the underlying operating system.  Porting Go to
+# a new architecture/operating system combination requires
+# some manual effort, though there are tools that automate
+# much of the process.  The auto-generated files have names
+# beginning with z.
+#
+# This script prints suggested commands to generate z files
+# for the current system.  Running those commands is not automatic.
+# This script is documentation more than anything else.
+#
+# * asm_${GOOS}_${GOARCH}.s
+#
+# This hand-written assembly file implements system call dispatch.
+# There are three entry points:
+#
+#      func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
+#      func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr);
+#      func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
+#
+# The first and second are the standard ones; they differ only in
+# how many arguments can be passed to the kernel.
+# The third is for low-level use by the ForkExec wrapper;
+# unlike the first two, it does not call into the scheduler to
+# let it know that a system call is running.
+#
+# * syscall_${GOOS}.go
+#
+# This hand-written Go file implements system calls that need
+# special handling and lists "//sys" comments giving prototypes
+# for ones that can be auto-generated.  Mksyscall reads those
+# comments to generate the stubs.
+#
+# * syscall_${GOOS}_${GOARCH}.go
+#
+# Same as syscall_${GOOS}.go except that it contains code specific
+# to ${GOOS} on one particular architecture.
+#
+# * types_${GOOS}.c
+#
+# This hand-written C file includes standard C headers and then
+# creates typedef or enum names beginning with a dollar sign
+# (use of $ in variable names is a gcc extension).  The hardest
+# part about preparing this file is figuring out which headers to
+# include and which symbols need to be #defined to get the
+# actual data structures that pass through to the kernel system calls.
+# Some C libraries present alternate versions for binary compatibility
+# and translate them on the way in and out of system calls, but
+# there is almost always a #define that can get the real ones.
+# See types_darwin.c and types_linux.c for examples.
+#
+# * types_${GOOS}_${GOARCH}.c
+#
+# Same as types_${GOOS}_${GOARCH}.go except that it contains
+# definitions specific to ${GOOS} one one particular architecture.
+#
+# * zerror_${GOOS}_${GOARCH}.go
+#
+# This machine-generated file defines the system's error numbers,
+# error strings, and signal numbers.  The generator is "mkerrors".
+# Usually no arguments are needed, but mkerrors will pass its
+# arguments on to godefs.
+#
+# * zsyscall_${GOOS}_${GOARCH}.go
+#
+# Generated by mksyscall; see syscall_${GOOS}.go above.
+#
+# * zsysnum_${GOOS}_${GOARCH}.go
+#
+# Generated by mksysnum_${GOOS}.
+#
+# * ztypes_${GOOS}_${GOARCH}.go
+#
+# Generated by godefs; see types_${GOOS}.c above.
+
+GOOSARCH="${GOOS}_${GOARCH}"
+
+# defaults
+mksyscall="mksyscall"
+mkerrors="mkerrors"
+
+case "$GOOSARCH" in
+_* | *_ | _)
+       echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
+       exit 1
+       ;;
+darwin_386)
+       mksyscall="mksyscall -l32"
+       mksysnum="mksysnum_darwin /home/rsc/pub/xnu-1228/bsd/kern/syscalls.master"
+       mktypes="godefs -gsyscall -f-m32"
+       ;;
+darwin_amd64)
+       mksysnum="mksysnum_darwin /home/rsc/pub/xnu-1228/bsd/kern/syscalls.master"
+       mktypes="godefs -gsyscall -f-m64"
+       mkerrors="mkerrors"
+       ;;
+linux_amd64)
+       mksysnum="mksysnum_linux /usr/include/asm/unistd_64.h"
+       mktypes="godefs -gsyscall -f-m64"
+       ;;
+*)
+       echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
+       exit 1
+       ;;
+esac
+
+echo "$mkerrors >zerrors_$GOOSARCH.go"
+echo "$mksyscall syscall_$GOOS.go syscall_$GOOSARCH.go >zsyscall_$GOOSARCH.go"
+echo "$mksysnum >zsysnum_$GOOSARCH.go"
+echo "$mktypes types_$GOOS.c types_$GOOSARCH.c >ztypes_$GOOSARCH.go"
+
+port=$(ls *.go | grep -v _)
+arch=$(ls *_$GOOSARCH.s *_$GOOSARCH.go *_$GOOS.go)
+all=$(ls $port $arch)  # sort them
+echo gobuild $all
diff --git a/src/lib/syscall/errstr.go b/src/lib/syscall/errstr.go
new file mode 100644 (file)
index 0000000..67a529d
--- /dev/null
@@ -0,0 +1,30 @@
+// 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
+
+import "syscall"
+
+func str(val int) string {  // do it here rather than with fmt to avoid dependency
+       if val < 0 {
+               return "-" + str(-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:len(buf)]);
+}
+
+func Errstr(errno int) string {
+       if errno < 0 || errno >= int(len(errors)) {
+               return "error " + str(errno)
+       }
+       return errors[errno]
+}
+
index 63d7821089accf48b83fc6e0d3018bff52d81e7e..58fb058635f6e5e97e9914ae9480a3c9ba7cb58a 100644 (file)
@@ -61,10 +61,6 @@ import (
 
 var ForkLock sync.RWMutex
 
-func CloseOnExec(fd int64) {
-       Fcntl(fd, F_SETFD, FD_CLOEXEC);
-}
-
 // Convert array of string to array
 // of NUL-terminated byte pointer.
 func StringArrayPtr(ss []string) []*byte {
@@ -76,36 +72,40 @@ func StringArrayPtr(ss []string) []*byte {
        return bb;
 }
 
-func Wait4(pid int64, wstatus *WaitStatus, options int64, rusage *Rusage)
-       (wpid, err int64)
-{
-       var s WaitStatus;
-       r1, r2, err1 := Syscall6(SYS_WAIT4,
-               pid,
-               int64(uintptr(unsafe.Pointer(&s))),
-               options,
-               int64(uintptr(unsafe.Pointer(rusage))), 0, 0);
-       if wstatus != nil {
-               *wstatus = s;
+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;
        }
-       return r1, err1;
+       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 int64 to pipe.
+// 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 []*byte, envv []*byte, dir *byte, fd []int64, pipe int64)
-       (pid int64, err int64)
+func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, dir *byte, fd []int, pipe int)
+       (pid int, err int)
 {
        // Declare all variables at top in case any
        // declarations require heap allocation (e.g., err1).
-       var r1, r2, err1 int64;
-       var nextfd int64;
+       var r1, r2, err1 uintptr;
+       var nextfd int;
        var i int;
 
        darwin := OS == "darwin";
@@ -114,7 +114,7 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, dir *byte, fd [
        // No more allocation or calls of non-assembly functions.
        r1, r2, err1 = RawSyscall(SYS_FORK, 0, 0, 0);
        if err1 != 0 {
-               return 0, err1
+               return 0, int(err1)
        }
 
        // On Darwin:
@@ -127,38 +127,38 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, dir *byte, fd [
 
        if r1 != 0 {
                // parent; return PID
-               return r1, 0
+               return int(r1), 0
        }
 
        // Fork succeeded, now in child.
 
        // Chdir
        if dir != nil {
-               r1, r2, err = RawSyscall(SYS_CHDIR, int64(uintptr(unsafe.Pointer(dir))), 0, 0);
-               if err != 0 {
+               r1, r2, err1 = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0);
+               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 = int64(len(fd));
+       nextfd = int(len(fd));
        if pipe < nextfd {
-               r1, r2, err = RawSyscall(SYS_DUP2, pipe, nextfd, 0);
-               if err != 0 {
+               r1, r2, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0);
+               if err1 != 0 {
                        goto childerror;
                }
-               RawSyscall(SYS_FCNTL, nextfd, F_SETFD, FD_CLOEXEC);
+               RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC);
                pipe = nextfd;
                nextfd++;
        }
        for i = 0; i < len(fd); i++ {
-               if fd[i] >= 0 && fd[i] < int64(i) {
-                       r1, r2, err = RawSyscall(SYS_DUP2, fd[i], nextfd, 0);
-                       if err != 0 {
+               if fd[i] >= 0 && fd[i] < int(i) {
+                       r1, r2, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0);
+                       if err1 != 0 {
                                goto childerror;
                        }
-                       RawSyscall(SYS_FCNTL, nextfd, F_SETFD, FD_CLOEXEC);
+                       RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC);
                        fd[i] = nextfd;
                        nextfd++;
                        if nextfd == pipe {     // don't stomp on pipe
@@ -170,22 +170,22 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, dir *byte, fd [
        // Pass 2: dup fd[i] down onto i.
        for i = 0; i < len(fd); i++ {
                if fd[i] == -1 {
-                       RawSyscall(SYS_CLOSE, int64(i), 0, 0);
+                       RawSyscall(SYS_CLOSE, uintptr(i), 0, 0);
                        continue;
                }
-               if fd[i] == int64(i) {
+               if fd[i] == int(i) {
                        // dup2(i, i) won't clear close-on-exec flag on Linux,
                        // probably not elsewhere either.
-                       r1, r2, err = RawSyscall(SYS_FCNTL, fd[i], F_SETFD, 0);
-                       if err != 0 {
+                       r1, r2, err1 = RawSyscall(SYS_FCNTL, uintptr(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.
-               r1, r2, err = RawSyscall(SYS_DUP2, fd[i], int64(i), 0);
-               if err != 0 {
+               r1, r2, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(i), 0);
+               if err1 != 0 {
                        goto childerror;
                }
        }
@@ -195,18 +195,18 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, dir *byte, fd [
        // Programs that know they inherit fds >= 3 will need
        // to set them close-on-exec.
        for i = len(fd); i < 3; i++ {
-               RawSyscall(SYS_CLOSE, int64(i), 0, 0);
+               RawSyscall(SYS_CLOSE, uintptr(i), 0, 0);
        }
 
        // Time to exec.
        r1, r2, err1 = RawSyscall(SYS_EXECVE,
-               int64(uintptr(unsafe.Pointer(argv0))),
-               int64(uintptr(unsafe.Pointer(&argv[0]))),
-               int64(uintptr(unsafe.Pointer(&envv[0]))));
+               uintptr(unsafe.Pointer(argv0)),
+               uintptr(unsafe.Pointer(&argv[0])),
+               uintptr(unsafe.Pointer(&envv[0])));
 
 childerror:
        // send error code on pipe
-       RawSyscall(SYS_WRITE, pipe, int64(uintptr(unsafe.Pointer(&err1))), 8);
+       RawSyscall(SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), uintptr(unsafe.Sizeof(err1)));
        for {
                RawSyscall(SYS_EXIT, 253, 0, 0);
        }
@@ -218,12 +218,13 @@ childerror:
 }
 
 // Combination of fork and exec, careful to be thread safe.
-func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int64)
-       (pid int64, err int64)
+func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int)
+       (pid int, err int)
 {
-       var p [2]int64;
-       var r1 int64;
-       var n, err1 int64;
+       var p [2]int;
+       var r1 int;
+       var n int;
+       var err1 uintptr;
        var wstatus WaitStatus;
 
        p[0] = -1;
@@ -244,13 +245,14 @@ func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int64
        ForkLock.Lock();
 
        // Allocate child status pipe close on exec.
-       if r1, err = Pipe(&p); err != 0 {
+       if err = Pipe(&p); err != 0 {
                goto error;
        }
-       if r1, err = Fcntl(p[0], F_SETFD, FD_CLOEXEC); err != 0 {
+       var val int;
+       if val, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != 0 {
                goto error;
        }
-       if r1, err = Fcntl(p[1], F_SETFD, FD_CLOEXEC); err != 0 {
+       if val, err = fcntl(p[1], F_SETFD, FD_CLOEXEC); err != 0 {
                goto error;
        }
 
@@ -269,11 +271,11 @@ func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int64
 
        // Read child error status from pipe.
        Close(p[1]);
-       n, r1, err = Syscall(SYS_READ, p[0], int64(uintptr(unsafe.Pointer(&err1))), 8);
+       n, err = read(p[0], (*byte)(unsafe.Pointer(&err1)), unsafe.Sizeof(err1));
        Close(p[0]);
        if err != 0 || n != 0 {
-               if n == 8 {
-                       err = err1;
+               if n == unsafe.Sizeof(err1) {
+                       err = int(err1);
                }
                if err == 0 {
                        err = EPIPE;
@@ -293,11 +295,11 @@ func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int64
 }
 
 // Ordinary exec.
-func Exec(argv0 string, argv []string, envv []string) (err int64) {
+func Exec(argv0 string, argv []string, envv []string) (err int) {
        r1, r2, err1 := RawSyscall(SYS_EXECVE,
-               int64(uintptr(unsafe.Pointer(StringBytePtr(argv0)))),
-               int64(uintptr(unsafe.Pointer(&StringArrayPtr(argv)[0]))),
-               int64(uintptr(unsafe.Pointer(&StringArrayPtr(envv)[0]))));
-       return err1;
+               uintptr(unsafe.Pointer(StringBytePtr(argv0))),
+               uintptr(unsafe.Pointer(&StringArrayPtr(argv)[0])),
+               uintptr(unsafe.Pointer(&StringArrayPtr(envv)[0])));
+       return int(err1);
 }
 
diff --git a/src/lib/syscall/mkerrors b/src/lib/syscall/mkerrors
new file mode 100755 (executable)
index 0000000..015f021
--- /dev/null
@@ -0,0 +1,94 @@
+#!/bin/sh
+# 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.
+
+
+# Generate Go code listing error values (ENAMETOOLONG etc)
+# and signal values (SIGALRM etc).  They're unrelated except
+# that we use the same method for finding them.
+
+errors=$(
+       echo '#include <errno.h>' |
+       # The gcc command line prints all the #defines
+       # it encounters while processing the input
+       gcc -x c - -E -dM |
+       egrep -h '#define E[A-Z0-9_]+ ' $files |
+       sed 's/#define //; s/ .*//'
+)
+
+signals=$(
+       echo '#include <sys/signal.h>' |
+       gcc -x c - -E -dM |
+       egrep -h '#define SIG[^_]' |
+       egrep -v '#define (SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))' |
+       sed 's/#define //; s/ .*//'
+)
+
+# Write godefs input.
+(
+       echo '#include <errno.h>'
+       echo '#include <signal.h>'
+       echo 'enum {'
+       for i in $errors $signals
+       do
+               echo '$'"$i = $i,"
+       done
+       echo '};'
+) >_errors.c
+
+echo '// mkerrors' "$@"
+echo '// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT'
+echo
+godefs -gsyscall "$@" _errors.c
+
+# Run C program to print error strings.
+(
+       echo "
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+
+#define nelem(x) (sizeof(x)/sizeof((x)[0]))
+
+enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below
+
+int errors[] = {
+"
+       for i in $errors
+       do
+               echo '  '$i,
+       done
+
+       echo '
+};
+
+int
+main(void)
+{
+       int i, j, e;
+       char buf[1024];
+
+       printf("\n\n// Error table\n");
+       printf("var errors = [...]string {\n");
+       for(i=0; i<nelem(errors); i++) {
+               e = errors[i];
+               for(j=0; j<i; j++)
+                       if(errors[j] == e)      // duplicate value
+                               goto next;
+               strcpy(buf, strerror(e));
+               // lowercase first letter: Bad -> bad, but STREAM -> STREAM.
+               if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
+                       buf[0] += a - A;
+               printf("\t%d: \"%s\",\n", e, buf);
+       next:;
+       }
+       printf("}\n\n");
+}
+
+'
+) >_errors.c
+
+gcc -o _errors _errors.c && ./_errors
+rm -f _errors.c _errors
diff --git a/src/lib/syscall/mksyscall b/src/lib/syscall/mksyscall
new file mode 100755 (executable)
index 0000000..20b5c26
--- /dev/null
@@ -0,0 +1,170 @@
+#!/usr/bin/perl
+# 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.
+
+# This program reads a file containing function prototypes
+# (like syscall_darwin.go) and generates system call bodies.
+# The prototypes 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.
+
+$cmdline = "mksyscall " . join(' ', @ARGV);
+$errors = 0;
+$_32bit = 0;
+
+if($ARGV[0] eq "-b32") {
+       $_32bit = "big-endian";
+       shift;
+} elsif($ARGV[0] eq "-l32") {
+       $_32bit = "little-endian";
+       shift;
+}
+
+if($ARGV[0] =~ /^-/) {
+       print STDERR "usage: mksyscall [-b32 | -l32] [file ...]\n";
+       exit 1;
+}
+
+sub parseparamlist($) {
+       my ($list) = @_;
+       $list =~ s/^\s*//;
+       $list =~ s/\s*$//;
+       if($list eq "") {
+               return ();
+       }
+       return split(/\s*,\s*/, $list);
+}
+
+sub parseparam($) {
+       my ($p) = @_;
+       if($p !~ /^(\S*) (\S*)$/) {
+               print STDERR "$ARGV:$.: malformed parameter: $p\n";
+               $errors = 1;
+               return ("xx", "int");
+       }
+       return ($1, $2);
+}
+
+$text = "";
+while(<>) {
+       chomp;
+       s/\s+/ /g;
+       s/^\s+//;
+       s/\s+$//;
+       next if !/^\/\/sys /;
+
+       # Line must be of the form
+       #       func Open(path string, mode int, perm int) (fd int, errno int)
+       # Split into name, in params, out params.
+       if(!/^\/\/sys (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(SYS_[A-Z0-9_]+))?$/) {
+               print STDERR "$ARGV:$.: malformed //sys declaration\n";
+               $errors = 1;
+               next;
+       }
+       my ($func, $in, $out, $sysname) = ($1, $2, $3, $4);
+
+       # Split argument lists on comma.
+       my @in = parseparamlist($in);
+       my @out = parseparamlist($out);
+
+       # Go function header.
+       $text .= sprintf "func %s(%s) (%s) {\n", $func, join(', ', @in), join(', ', @out);
+
+       # Prepare arguments to Syscall.
+       my @args = ();
+       my $n = 0;
+       foreach my $p (@in) {
+               my ($name, $type) = parseparam($p);
+               if($type =~ /^\*/) {
+                       push @args, "uintptr(unsafe.Pointer($name))";
+               } elsif($type eq "string") {
+                       push @args, "uintptr(unsafe.Pointer(StringBytePtr($name)))";
+               } elsif($type =~ /^\[\](.*)/) {
+                       # Convert slice into pointer, length.
+                       # Have to be careful not to take address of &a[0] if len == 0:
+                       # pass nil in that case.
+                       $text .= "\tvar _p$n *$1;\n";
+                       $text .= "\tif len($name) > 0 { _p$n = \&${name}[0]; }\n";
+                       push @args, "uintptr(unsafe.Pointer(_p$n))", "uintptr(len($name))";
+                       $n++;
+               } elsif($type eq "int64" && $_32bit ne "") {
+                       if($_32bit eq "big-endian") {
+                               push @args, "uintptr($name >> 32)", "uintptr($name)";
+                       } else {
+                               push @args, "uintptr($name)", "uintptr($name >> 32)";
+                       }
+               } else {
+                       push @args, "uintptr($name)";
+               }
+       }
+
+       # Determine which form to use; pad args with zeros.
+       my $asm = "Syscall";
+       if(@args <= 3) {
+               while(@args < 3) {
+                       push @args, "0";
+               }
+       } elsif(@args <= 6) {
+               $asm = "Syscall6";
+               while(@args < 6) {
+                       push @args, "0";
+               }
+       } else {
+               print STDERR "$ARGV:$.: too many arguments to system call\n";
+       }
+
+       # System call number.
+       if($sysname eq "") {
+               $sysname = "SYS_$func";
+               $sysname =~ s/([a-z])([A-Z])/${1}_$2/g; # turn FooBar into Foo_Bar
+               $sysname =~ y/a-z/A-Z/;
+       }
+
+       # Actual call.
+       my $args = join(', ', @args);
+       $text .= "\tr0, r1, e1 := $asm($sysname, $args);\n";
+
+       # Assign return values.
+       for(my $i=0; $i<@out; $i++) {
+               my $p = $out[$i];
+               my ($name, $type) = parseparam($p);
+               my $reg = "";
+               if($name eq "errno") {
+                       $reg = "e1";
+               } else {
+                       $reg = sprintf("r%d", $i);
+               }
+               if($type eq "bool") {
+                       $reg = "$reg != 0";
+               }
+               $text .= "\t$name = $type($reg);\n";
+       }
+
+       $text .= "\treturn;\n";
+       $text .= "}\n\n";
+}
+
+if($errors) {
+       exit 1;
+}
+
+print <<EOF;
+// $cmdline
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package syscall
+
+import (
+       "syscall";
+       "unsafe";
+)
+
+$text
+
+EOF
+exit 0;
diff --git a/src/lib/syscall/mksysnum_darwin b/src/lib/syscall/mksysnum_darwin
new file mode 100755 (executable)
index 0000000..74e2dfd
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/perl
+# 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.
+#
+# Generate system call table for Darwin from master list
+# (for example, xnu-1228/bsd/kern/syscalls.master).
+
+my $command = "mksysnum_darwin " . join(' ', @ARGV);
+
+print <<EOF;
+// $command
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+EOF
+
+while(<>){
+       if(/^([0-9]+)\s+ALL\s+({ \S+\s+(\w+).*})/){
+               my $num = $1;
+               my $proto = $2;
+               my $name = "SYS_$3";
+               $name =~ y/a-z/A-Z/;
+
+               # There are multiple entries for enosys and nosys, so comment them out.
+               if($name =~ /^SYS_E?NOSYS$/){
+                       $name = "// $name";
+               }
+
+               print " $name = $num;  // $proto\n";
+       }
+}
+
+print <<EOF;
+)
+EOF
index 93611c86e6f16119436fd1120b58ca01efa07644..5ee44e3e84f34eaa3d4544645a004ec593147bb4 100644 (file)
 // the manuals for the appropriate operating system.
 package syscall
 
-/*
- * Foundation of system call interface.
- */
+import (
+       "syscall";
+       "unsafe";
+)
 
-func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64);
-func Syscall6(trap int64, a1, a2, a3, a4, a5, a6 int64) (r1, r2, err int64);
-func RawSyscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64);
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
+func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
 
-/*
- * Used to convert file names to byte arrays for passing to kernel,
- * but useful elsewhere too.
- */
-func StringBytePtr(s string) *byte {
+// 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[0];
+       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];
 }
diff --git a/src/lib/syscall/syscall_darwin.go b/src/lib/syscall/syscall_darwin.go
new file mode 100644 (file)
index 0000000..6909d07
--- /dev/null
@@ -0,0 +1,674 @@
+// 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.
+
+// Darwin system calls.
+// This file is compiled as ordinary Go code,
+// but it is also input to mksyscall,
+// which parses the //sys lines and generates system call stubs.
+// Note that sometimes we use a lowercase //sys name and
+// wrap it in our own nicer implementation.
+
+package syscall
+
+import (
+       "syscall";
+       "unsafe";
+)
+
+const OS = "darwin"
+
+/*
+ * Pseudo-system calls
+ */
+// The const provides a compile-time constant so clients
+// can adjust to whether there is a working Getwd and avoid
+// even linking this function into the binary.  See ../os/getwd.go.
+const ImplementsGetwd = false
+
+func Getwd() (string, int) {
+       return "", ENOTSUP;
+}
+
+
+/*
+ * Wrapped
+ */
+
+//sys  getgroups(ngid int, gid *_Gid_t) (n int, errno int)
+//sys  setgroups(ngid int, gid *_Gid_t) (errno 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 16 on BSD.
+       if n < 0 || n > 1000 {
+               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;
+}
+
+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]);
+}
+
+// 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.
+
+type WaitStatus uint32
+
+const (
+       mask = 0x7F;
+       core = 0x80;
+       shift = 8;
+
+       exited = 0;
+       stopped = 0x7F;
+)
+
+func (w WaitStatus) Exited() bool {
+       return w&mask == exited;
+}
+
+func (w WaitStatus) ExitStatus() int {
+       if w&mask != exited {
+               return -1;
+       }
+       return int(w >> shift);
+}
+
+func (w WaitStatus) Signaled() bool {
+       return w&mask != stopped && w&mask != 0;
+}
+
+func (w WaitStatus) Signal() int {
+       sig := int(w & mask);
+       if sig == stopped || sig == 0 {
+               return -1;
+       }
+       return sig;
+}
+
+func (w WaitStatus) CoreDump() bool {
+       return w.Signaled() && w&core != 0;
+}
+
+func (w WaitStatus) Stopped() bool {
+       return w&mask == stopped && w>>shift != SIGSTOP;
+}
+
+func (w WaitStatus) Continued() bool {
+       return w&mask == stopped && w>>shift == SIGSTOP;
+}
+
+func (w WaitStatus) StopSignal() int {
+       if !w.Stopped() {
+               return -1;
+       }
+       return int(w >> shift) & 0xFF;
+}
+
+//sys  wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int)
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
+       var status _C_int;
+       wpid, errno = wait4(pid, &status, options, rusage);
+       if wstatus != nil {
+               *wstatus = WaitStatus(status);
+       }
+       return;
+}
+
+//sys  pipe() (r int, w int, errno int)
+func Pipe(p []int) (errno int) {
+       if len(p) != 2 {
+               return EINVAL;
+       }
+       p[0], p[1], errno = pipe();
+       return;
+}
+
+// TODO(rsc): How does 386 return an int64 newoffset?
+//sys  lseek(fd int, offset int64, whence int) (newoffset uintptr, errno int)
+func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
+       n, e := lseek(fd, offset, whence);
+       return int64(n), e;
+}
+
+//sys  gettimeofday(tp *Timeval) (sec int64, usec int32, errno int)
+func Gettimeofday(tv *Timeval) (errno int) {
+       // The tv passed to gettimeofday must be non-nil
+       // but is otherwise unused.  The answers come back
+       // in the two registers.
+       sec, usec, err := gettimeofday(tv);
+       tv.Sec = sec;
+       tv.Usec = usec;
+       return err;
+}
+
+func Sleep(ns int64) (errno int) {
+       tv := NsecToTimeval(ns);
+       return Select(0, nil, nil, nil, &tv);
+}
+
+//sys  accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int)
+//sys  bind(s int, addr uintptr, addrlen _Socklen) (errno int)
+//sys  connect(s int, addr uintptr, addrlen _Socklen) (errno int)
+//sys  socket(domain int, typ int, proto int) (fd int, errno int)
+//sys  setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int)
+
+// For testing: clients can set this flag to force
+// creation of IPv6 sockets to return EAFNOSUPPORT.
+var SocketDisableIPv6 bool
+
+type Sockaddr interface {
+       sockaddr() (ptr uintptr, len _Socklen, errno int);      // lowercase; only we can define Sockaddrs
+}
+
+type SockaddrInet4 struct {
+       Port int;
+       Addr [4]byte;
+       raw RawSockaddrInet4;
+}
+
+func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) {
+       if sa.Port < 0 || sa.Port > 0xFFFF {
+               return 0, 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 uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0;
+}
+
+type SockaddrInet6 struct {
+       Port int;
+       Addr [16]byte;
+       raw RawSockaddrInet6;
+}
+
+func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) {
+       if sa.Port < 0 || sa.Port > 0xFFFF {
+               return 0, 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 uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0;
+}
+
+type SockaddrUnix struct {
+       Name string;
+       raw RawSockaddrUnix;
+}
+
+func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
+       name := sa.Name;
+       n := len(name);
+       if n >= len(sa.raw.Path) || n == 0 {
+               return 0, 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]);
+       }
+       return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(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;
+}
+
+func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
+       var rsa RawSockaddrAny;
+       var len _Socklen = SizeofSockaddrAny;
+       nfd, errno = accept(fd, &rsa, &len);
+       if errno != 0 {
+               return;
+       }
+       sa, errno = anyToSockaddr(&rsa);
+       if errno != 0 {
+               Close(nfd);
+               nfd = 0;
+       }
+       return;
+}
+
+func Bind(fd int, sa Sockaddr) (errno int) {
+       ptr, n, err := sa.sockaddr();
+       if err != 0 {
+               return err;
+       }
+       return bind(fd, ptr, n);
+}
+
+func Connect(fd int, sa Sockaddr) (errno int) {
+       ptr, n, err := sa.sockaddr();
+       if err != 0 {
+               return err;
+       }
+       return connect(fd, ptr, n);
+}
+
+func Socket(domain, typ, proto int) (fd, errno int) {
+       if domain == AF_INET6 && SocketDisableIPv6 {
+               return -1, EAFNOSUPPORT
+       }
+       fd, errno = socket(domain, typ, proto);
+       return;
+}
+
+func SetsockoptInt(fd, level, opt int, value int) (errno int) {
+       var n = int32(value);
+       return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4);
+}
+
+func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
+       return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(tv)), unsafe.Sizeof(*tv));
+}
+
+func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
+       return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(l)), unsafe.Sizeof(*l));
+}
+
+//sys  kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int)
+func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, errno int) {
+       var change, event uintptr;
+       if len(changes) > 0 {
+               change = uintptr(unsafe.Pointer(&changes[0]));
+       }
+       if len(events) > 0 {
+               event = uintptr(unsafe.Pointer(&events[0]));
+       }
+       return kevent(kq, change, len(changes), event, len(events), timeout);
+}
+
+// TODO: wrap
+//     Acct(name nil-string) (errno int)
+//     Futimes(fd int, timeval *Timeval) (errno int)   // Pointer to 2 timevals!
+//     Gethostuuid(uuid *byte, timeout *Timespec) (errno int)
+//     Getpeername(fd int, addr *Sockaddr, addrlen *int) (errno int)
+//     Getsockname(fd int, addr *Sockaddr, addrlen *int) (errno int)
+//     Getsockopt(s int, level int, name int, val *byte, vallen *int) (errno int)
+//     Madvise(addr *byte, len int, behav int) (errno int)
+//     Mprotect(addr *byte, len int, prot int) (errno int)
+//     Msync(addr *byte, len int, flags int) (errno int)
+//     Munmap(addr *byte, len int) (errno int)
+//     Ptrace(req int, pid int, addr uintptr, data int) (ret uintptr, errno int)
+//     Recvfrom(s int, buf *byte, nbuf int, flags int, from *Sockaddr, fromlen *int) (n int, errno int)
+//     Recvmsg(s int, msg *Msghdr, flags int) (n int, errno int)
+//     Sendmsg(s int, msg *Msghdr, flags int) (n int, errno int)
+//     Sendto(s int, buf *byte, nbuf int, flags int, to *Sockaddr, addrlen int) (errno int)
+//     Utimes(path string, timeval *Timeval) (errno int)       // Pointer to 2 timevals!
+//sys  fcntl(fd int, cmd int, arg int) (val int, errno int)
+
+
+/*
+ * Exposed directly
+ */
+//sys  Access(path string, flags int) (errno int)
+//sys  Adjtime(delta *Timeval, olddelta *Timeval) (errno int)
+//sys  Chdir(path string) (errno int)
+//sys  Chflags(path string, flags int) (errno int)
+//sys  Chmod(path string, mode int) (errno int)
+//sys  Chown(path string, uid int, gid int) (errno int)
+//sys  Chroot(path string) (errno int)
+//sys  Close(fd int) (errno int)
+//sys  Dup(fd int) (nfd int, errno int)
+//sys  Dup2(from int, to int) (errno int)
+//sys  Exchangedata(path1 string, path2 string, options int) (errno int)
+//sys  Exit(code int)
+//sys  Fchdir(fd int) (errno int)
+//sys  Fchflags(path string, flags int) (errno int)
+//sys  Fchmod(fd int, mode int) (errno int)
+//sys  Fchown(fd int, uid int, gid int) (errno int)
+//sys  Flock(fd int, how int) (errno int)
+//sys  Fpathconf(fd int, name int) (val int, errno int)
+//sys  Fstat(fd int, stat *Stat_t) (errno int) = SYS_FSTAT64
+//sys  Fstatfs(fd int, stat *Statfs_t) (errno int) = SYS_FSTATFS64
+//sys  Fsync(fd int) (errno int)
+//sys  Ftruncate(fd int, length int64) (errno int)
+//sys  Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) = SYS_GETDIRENTRIES64
+//sys  Getdtablesize() (size int)
+//sys  Getegid() (egid int)
+//sys  Geteuid() (uid int)
+//sys  Getfsstat(buf []Statfs_t, flags int) (n int, errno int) = SYS_GETFSSTAT64
+//sys  Getgid() (gid int)
+//sys  Getpgid(pid int) (pgid int, errno int)
+//sys  Getpgrp() (pgrp int)
+//sys  Getpid() (pid int)
+//sys  Getppid() (ppid int)
+//sys  Getpriority(which int, who int) (prio int, errno int)
+//sys  Getrlimit(which int, lim *Rlimit) (errno int)
+//sys  Getrusage(who int, rusage *Rusage) (errno int)
+//sys  Getsid(pid int) (sid int, errno int)
+//sys  Getuid() (uid int)
+//sys  Issetugid() (tainted bool)
+//sys  Kill(pid int, signum int, posix int) (errno int)
+//sys  Kqueue() (fd int, errno int)
+//sys  Lchown(path string, uid int, gid int) (errno int)
+//sys  Link(path string, link string) (errno int)
+//sys  Listen(s int, backlog int) (errno int)
+//sys  Lstat(path string, stat *Stat_t) (errno int) = SYS_LSTAT64
+//sys  Mkdir(path string, mode int) (errno int)
+//sys  Mkfifo(path string, mode int) (errno int)
+//sys  Mknod(path string, mode int, dev int) (errno int)
+//sys  Open(path string, mode int, perm int) (fd int, errno int)
+//sys  Pathconf(path string, name int) (val int, errno int)
+//sys  Pread(fd int, p []byte, offset int64) (n int, errno int)
+//sys  Pwrite(fd int, p []byte, offset int64) (n int, errno int)
+//sys  Read(fd int, p []byte) (n int, errno int)
+//sys  Readlink(path string, buf []byte) (n int, errno int)
+//sys  Rename(from string, to string) (errno int)
+//sys  Revoke(path string) (errno int)
+//sys  Rmdir(path string) (errno int)
+//sys  Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int)
+//sys  Setegid(egid int) (errno int)
+//sys  Seteuid(euid int) (errno int)
+//sys  Setgid(gid int) (errno int)
+//sys  Setlogin(name string) (errno int)
+//sys  Setpgid(pid int, pgid int) (errno int)
+//sys  Setpriority(which int, who int, prio int) (errno int)
+//sys  Setprivexec(flag int) (errno int)
+//sys  Setregid(rgid int, egid int) (errno int)
+//sys  Setreuid(ruid int, euid int) (errno int)
+//sys  Setrlimit(which int, lim *Rlimit) (errno int)
+//sys  Setsid() (pid int, errno int)
+//sys  Settimeofday(tp *Timeval) (errno int)
+//sys  Setuid(uid int) (errno int)
+//sys  Stat(path string, stat *Stat_t) (errno int) = SYS_STAT64
+//sys  Statfs(path string, stat *Statfs_t) (errno int) = SYS_STATFS64
+//sys  Symlink(path string, link string) (errno int)
+//sys  Sync() (errno int)
+//sys  Truncate(path string, length int64) (errno int)
+//sys  Umask(newmask int) (errno int)
+//sys  Undelete(path string) (errno int)
+//sys  Unlink(path string) (errno int)
+//sys  Unmount(path string, flags int) (errno int)
+//sys  Write(fd int, p []byte) (n int, errno int)
+//sys  read(fd int, buf *byte, nbuf int) (n int, errno int)
+//sys  write(fd int, buf *byte, nbuf int) (n int, errno int)
+
+
+/*
+ * Unimplemented
+ */
+// Profil
+// Sigaction
+// Sigprocmask
+// Getlogin
+// Sigpending
+// Sigaltstack
+// Ioctl
+// Reboot
+// Execve
+// Vfork
+// Sbrk
+// Sstk
+// Ovadvise
+// Mincore
+// Setitimer
+// Swapon
+// Select
+// Sigsuspend
+// Readv
+// Writev
+// Nfssvc
+// Getfh
+// Quotactl
+// Mount
+// Csops
+// Waitid
+// Add_profil
+// Kdebug_trace
+// Sigreturn
+// Mmap
+// __Sysctl
+// Mlock
+// Munlock
+// Atsocket
+// Kqueue_from_portset_np
+// Kqueue_portset
+// Getattrlist
+// Setattrlist
+// Getdirentriesattr
+// Searchfs
+// Delete
+// Copyfile
+// Poll
+// Watchevent
+// Waitevent
+// Modwatch
+// Getxattr
+// Fgetxattr
+// Setxattr
+// Fsetxattr
+// Removexattr
+// Fremovexattr
+// Listxattr
+// Flistxattr
+// Fsctl
+// Initgroups
+// Posix_spawn
+// Nfsclnt
+// Fhopen
+// Minherit
+// Semsys
+// Msgsys
+// Shmsys
+// Semctl
+// Semget
+// Semop
+// Msgctl
+// Msgget
+// Msgsnd
+// Msgrcv
+// Shmat
+// Shmctl
+// Shmdt
+// Shmget
+// Shm_open
+// Shm_unlink
+// Sem_open
+// Sem_close
+// Sem_unlink
+// Sem_wait
+// Sem_trywait
+// Sem_post
+// Sem_getvalue
+// Sem_init
+// Sem_destroy
+// Open_extended
+// Umask_extended
+// Stat_extended
+// Lstat_extended
+// Fstat_extended
+// Chmod_extended
+// Fchmod_extended
+// Access_extended
+// Settid
+// Gettid
+// Setsgroups
+// Getsgroups
+// Setwgroups
+// Getwgroups
+// Mkfifo_extended
+// Mkdir_extended
+// Identitysvc
+// Shared_region_check_np
+// Shared_region_map_np
+// __pthread_mutex_destroy
+// __pthread_mutex_init
+// __pthread_mutex_lock
+// __pthread_mutex_trylock
+// __pthread_mutex_unlock
+// __pthread_cond_init
+// __pthread_cond_destroy
+// __pthread_cond_broadcast
+// __pthread_cond_signal
+// Setsid_with_pid
+// __pthread_cond_timedwait
+// Aio_fsync
+// Aio_return
+// Aio_suspend
+// Aio_cancel
+// Aio_error
+// Aio_read
+// Aio_write
+// Lio_listio
+// __pthread_cond_wait
+// Iopolicysys
+// Mlockall
+// Munlockall
+// __pthread_kill
+// __pthread_sigmask
+// __sigwait
+// __disable_threadsignal
+// __pthread_markcancel
+// __pthread_canceled
+// __semwait_signal
+// Proc_info
+// Sendfile
+// Stat64_extended
+// Lstat64_extended
+// Fstat64_extended
+// __pthread_chdir
+// __pthread_fchdir
+// Audit
+// Auditon
+// Getauid
+// Setauid
+// Getaudit
+// Setaudit
+// Getaudit_addr
+// Setaudit_addr
+// Auditctl
+// Bsdthread_create
+// Bsdthread_terminate
+// Stack_snapshot
+// Bsdthread_register
+// Workq_open
+// Workq_ops
+// __mac_execve
+// __mac_syscall
+// __mac_get_file
+// __mac_set_file
+// __mac_get_link
+// __mac_set_link
+// __mac_get_proc
+// __mac_set_proc
+// __mac_get_fd
+// __mac_set_fd
+// __mac_get_pid
+// __mac_get_lcid
+// __mac_get_lctx
+// __mac_set_lctx
+// Setlcid
+// Read_nocancel
+// Write_nocancel
+// Open_nocancel
+// Close_nocancel
+// Wait4_nocancel
+// Recvmsg_nocancel
+// Sendmsg_nocancel
+// Recvfrom_nocancel
+// Accept_nocancel
+// Msync_nocancel
+// Fcntl_nocancel
+// Select_nocancel
+// Fsync_nocancel
+// Connect_nocancel
+// Sigsuspend_nocancel
+// Readv_nocancel
+// Writev_nocancel
+// Sendto_nocancel
+// Pread_nocancel
+// Pwrite_nocancel
+// Waitid_nocancel
+// Poll_nocancel
+// Msgsnd_nocancel
+// Msgrcv_nocancel
+// Sem_wait_nocancel
+// Aio_suspend_nocancel
+// __sigwait_nocancel
+// __semwait_signal_nocancel
+// __mac_mount
+// __mac_get_mount
+// __mac_getfsstat
+
diff --git a/src/lib/syscall/syscall_darwin_amd64.go b/src/lib/syscall/syscall_darwin_amd64.go
new file mode 100644 (file)
index 0000000..2f576ad
--- /dev/null
@@ -0,0 +1,28 @@
+// 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
+
+import "syscall"
+
+func TimespecToNsec(ts Timespec) int64 {
+       return int64(ts.Sec)*1e9 + int64(ts.Nsec);
+}
+
+func NsecToTimespec(nsec int64) (ts Timespec) {
+       ts.Sec = nsec / 1e9;
+       ts.Nsec = 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.Usec = int32(nsec%1e9 / 1e3);
+       tv.Sec = int64(nsec/1e9);
+       return;
+}
diff --git a/src/lib/syscall/syscall_linux.go b/src/lib/syscall/syscall_linux.go
new file mode 100644 (file)
index 0000000..e89c9bc
--- /dev/null
@@ -0,0 +1,636 @@
+// 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.
+
+// Linux system calls.
+// This file is compiled as ordinary Go code,
+// but it is also input to mksyscall,
+// which parses the //sys lines and generates system call stubs.
+// Note that sometimes we use a lowercase //sys name and
+// wrap it in our own nicer implementation.
+
+package syscall
+
+import (
+       "syscall";
+       "unsafe";
+)
+
+const OS = "linux"
+
+/*
+ * Wrapped
+ */
+
+//sys  pipe(p *[2]_C_int) (errno int)
+func Pipe(p []int) (errno int) {
+       if len(p) != 2 {
+               return EINVAL;
+       }
+       var pp [2]_C_int;
+       errno = pipe(&pp);
+       p[0] = int(pp[0]);
+       p[1] = int(pp[1]);
+       return;
+}
+
+//sys  utimes(path string, times *[2]Timeval) (errno 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  futimesat(dirfd int, path string, times *[2]Timeval) (errno int)
+func Futimesat(dirfd int, path string, tv []Timeval) (errno int) {
+       if len(tv) != 2 {
+               return EINVAL;
+       }
+       return futimesat(dirfd, path, (*[2]Timeval)(unsafe.Pointer(&tv[0])));
+}
+
+const ImplementsGetwd = true;
+
+//sys  Getcwd(buf []byte) (n int, errno int)
+func Getwd() (wd string, errno int) {
+       var buf [PathMax]byte;
+       n, err := Getcwd(&buf);
+       if err != 0 {
+               return "", err;
+       }
+       // Getcwd returns the number of bytes written to buf, including the NUL.
+       if n < 1|| n > len(buf) || buf[n-1] != 0 {
+               return "", EINVAL;
+       }
+       return string(buf[0:n-1]), 0
+}
+
+//sys  getgroups(n int, list *_Gid_t) (nn int, errno int)
+//sys  setgroups(n int, list *_Gid_t) (errno 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;
+}
+
+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
+
+// 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;
+}
+
+//sys  wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int)
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
+       var status _C_int;
+       wpid, errno = wait4(pid, &status, options, rusage);
+       if wstatus != nil {
+               *wstatus = WaitStatus(status);
+       }
+       return;
+}
+
+func Sleep(nsec int64) (errno int) {
+       tv := NsecToTimeval(nsec);
+       n, err := Select(0, nil, nil, nil, &tv);
+       return err;
+}
+
+//sys  accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int)
+//sys  bind(s int, addr uintptr, addrlen _Socklen) (errno int)
+//sys  connect(s int, addr uintptr, addrlen _Socklen) (errno int)
+//sys  socket(domain int, typ int, proto int) (fd int, errno int)
+//sys  setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int)
+//sys  Listen(s int, n int) (errno int)
+
+// For testing: clients can set this flag to force
+// creation of IPv6 sockets to return EAFNOSUPPORT.
+var SocketDisableIPv6 bool
+
+type Sockaddr interface {
+       sockaddr() (ptr uintptr, len _Socklen, errno int);      // lowercase; only we can define Sockaddrs
+}
+
+type SockaddrInet4 struct {
+       Port int;
+       Addr [4]byte;
+       raw RawSockaddrInet4;
+}
+
+func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) {
+       if sa.Port < 0 || sa.Port > 0xFFFF {
+               return 0, 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 uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet4, 0;
+}
+
+type SockaddrInet6 struct {
+       Port int;
+       Addr [16]byte;
+       raw RawSockaddrInet6;
+}
+
+func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) {
+       if sa.Port < 0 || sa.Port > 0xFFFF {
+               return 0, 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 uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet6, 0;
+}
+
+type SockaddrUnix struct {
+       Name string;
+       raw RawSockaddrUnix;
+}
+
+func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
+       name := sa.Name;
+       n := len(name);
+       if n >= len(sa.raw.Path) || n == 0 {
+               return 0, 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 uintptr(unsafe.Pointer(&sa.raw)), 1 + _Socklen(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;
+}
+
+func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
+       var rsa RawSockaddrAny;
+       var len _Socklen = SizeofSockaddrAny;
+       nfd, errno = accept(fd, &rsa, &len);
+       if errno != 0 {
+               return;
+       }
+       sa, errno = anyToSockaddr(&rsa);
+       if errno != 0 {
+               Close(nfd);
+               nfd = 0;
+       }
+       return;
+}
+
+func Bind(fd int, sa Sockaddr) (errno int) {
+       ptr, n, err := sa.sockaddr();
+       if err != 0 {
+               return err;
+       }
+       return bind(fd, ptr, n);
+}
+
+func Connect(fd int, sa Sockaddr) (errno int) {
+       ptr, n, err := sa.sockaddr();
+       if err != 0 {
+               return err;
+       }
+       return connect(fd, ptr, n);
+}
+
+func Socket(domain, typ, proto int) (fd, errno int) {
+       if domain == AF_INET6 && SocketDisableIPv6 {
+               return -1, EAFNOSUPPORT
+       }
+       fd, errno = socket(domain, typ, proto);
+       return;
+}
+
+func SetsockoptInt(fd, level, opt int, value int) (errno int) {
+       var n = int32(value);
+       return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4);
+}
+
+func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
+       return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(tv)), unsafe.Sizeof(*tv));
+}
+
+func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
+       return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(l)), unsafe.Sizeof(*l));
+}
+
+// Sendto
+// Recvfrom
+// Sendmsg
+// Recvmsg
+// Getsockname
+// Getpeername
+// Socketpair
+// Getsockopt
+
+/*
+ * Direct access
+ */
+//sys  Access(path string, mode int) (errno int)
+//sys  Acct(path string) (errno int)
+//sys  Adjtimex(buf *Timex) (state int, errno int)
+//sys  Chdir(path string) (errno int)
+//sys  Chmod(path string, mode int) (errno int)
+//sys  Chown(path string, uid int, gid int) (errno int)
+//sys  Chroot(path string) (errno int)
+//sys  Close(fd int) (errno int)
+//sys  Creat(path string, mode int) (fd int, errno int)
+//sys  Dup(oldfd int) (fd int, errno int)
+//sys  Dup2(oldfd int, newfd int) (fd int, errno int)
+//sys  EpollCreate(size int) (fd int, errno int)
+//sys  EpollCtl(epfd int, op int, fd int, event *EpollEvent) (errno int)
+//sys  EpollWait(epfd int, events []EpollEvent, msec int) (n int, errno int)
+//sys  Exit(code int) = SYS_EXIT_GROUP
+//sys  Faccessat(dirfd int, path string, mode int, flags int) (errno int)
+//sys  Fallocate(fd int, mode int, off int64, len int64) (errno int)
+//sys  Fchdir(fd int) (errno int)
+//sys  Fchmod(fd int, mode int) (errno int)
+//sys  Fchmodat(dirfd int, path string, mode int, flags int) (errno int)
+//sys  Fchown(fd int, uid int, gid int) (errno int)
+//sys  Fchownat(dirfd int, path string, uid int, gid int, flags int) (errno int)
+//sys  fcntl(fd int, cmd int, arg int) (val int, errno int)
+//sys  Fdatasync(fd int) (errno int)
+//sys  Fstat(fd int, stat *Stat_t) (errno int)
+//sys  Fstatfs(fd int, buf *Statfs_t) (errno int)
+//sys  Fsync(fd int) (errno int)
+//sys  Ftruncate(fd int, length int64) (errno int)
+//sys  Getdents(fd int, buf []byte) (n int, errno int) = SYS_GETDENTS64
+//sys  Getegid() (egid int)
+//sys  Geteuid() (euid int)
+//sys  Getgid() (gid int)
+//sys  Getpgid(pid int) (pgid int, errno int)
+//sys  Getpgrp() (pid int)
+//sys  Getpid() (pid int)
+//sys  Getppid() (ppid int)
+//sys  Getrlimit(resource int, rlim *Rlimit) (errno int)
+//sys  Getrusage(who int, rusage *Rusage) (errno int)
+//sys  Gettid() (tid int)
+//sys  Gettimeofday(tv *Timeval) (errno int)
+//sys  Getuid() (uid int)
+//sys  Ioperm(from int, num int, on int) (errno int)
+//sys  Iopl(level int) (errno int)
+//sys  Kill(pid int, sig int) (errno int)
+//sys  Klogctl(typ int, buf []byte) (n int, errno int) = SYS_SYSLOG
+//sys  Lchown(path string, uid int, gid int) (errno int)
+//sys  Link(oldpath string, newpath string) (errno int)
+//sys  Lstat(path string, stat *Stat_t) (errno int)
+//sys  Mkdir(path string, mode int) (errno int)
+//sys  Mkdirat(dirfd int, path string, mode int) (errno int)
+//sys  Mknod(path string, mode int, dev int) (errno int)
+//sys  Mknodat(dirfd int, path string, mode int, dev int) (errno int)
+//sys  Nanosleep(time *Timespec, leftover *Timespec) (errno int)
+//sys  Open(path string, mode int, perm int) (fd int, errno int)
+//sys  Openat(dirfd int, path string, flags int, mode int) (fd int, errno int)
+//sys  Pause() (errno int)
+//sys  PivotRoot(newroot string, putold string) (errno int) = SYS_PIVOT_ROOT
+//sys  Pread(fd int, p []byte, offset int64) (n int, errno int) = SYS_PREAD64
+//sys  Pwrite(fd int, p []byte, offset int64) (n int, errno int) = SYS_PWRITE64
+//sys  Read(fd int, p []byte) (n int, errno int)
+//sys  Readlink(path string, buf []byte) (n int, errno int)
+//sys  Rename(oldpath string, newpath string) (errno int)
+//sys  Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (errno int)
+//sys  Rmdir(path string) (errno int)
+//sys  Seek(fd int, offset int64, whence int) (off int64, errno int) = SYS_LSEEK
+//sys  Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, errno int)
+//sys  Setdomainname(p []byte) (errno int)
+//sys  Setfsgid(gid int) (errno int)
+//sys  Setfsuid(uid int) (errno int)
+//sys  Setgid(gid int) (errno int)
+//sys  Sethostname(p []byte) (errno int)
+//sys  Setpgid(pid int, pgid int) (errno int)
+//sys  Setregid(rgid int, egid int) (errno int)
+//sys  Setresgid(rgid int, egid int, sgid int) (errno int)
+//sys  Setresuid(ruid int, euid int, suid int) (errno int)
+//sys  Setreuid(ruid int, euid int) (errno int)
+//sys  Setrlimit(resource int, rlim *Rlimit) (errno int)
+//sys  Setsid() (pid int)
+//sys  Settimeofday(tv *Timeval) (errno int)
+//sys  Setuid(uid int) (errno int)
+//sys  Shutdown(fd int, how int) (errno int)
+//sys  Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, errno int)
+//sys  Stat(path string, stat *Stat_t) (errno int)
+//sys  Statfs(path string, buf *Statfs_t) (errno int)
+//sys  Symlink(oldpath string, newpath string) (errno int)
+//sys  Sync()
+//sys  SyncFileRange(fd int, off int64, n int64, flags int) (errno int)
+//sys  Sysinfo(info *Sysinfo_t) (errno int)
+//sys  Tee(rfd int, wfd int, len int, flags int) (n int64, errno int)
+//sys  Tgkill(tgid int, tid int, sig int) (errno int)
+//sys  Time(t *Time_t) (tt Time_t, errno int)
+//sys  Times(tms *Tms) (ticks uintptr, errno int)
+//sys  Truncate(path string, length int64) (errno int)
+//sys  Umask(mask int) (oldmask int)
+//sys  Uname(buf *Utsname) (errno int)
+//sys  Unlink(path string) (errno int)
+//sys  Unlinkat(dirfd int, path string) (errno int)
+//sys  Unshare(flags int) (errno int)
+//sys  Ustat(dev int, ubuf *Ustat_t) (errno int)
+//sys  Utime(path string, buf *Utimbuf) (errno int)
+//sys  Write(fd int, p []byte) (n int, errno int)
+//sys  exitThread(code int) (errno int) = SYS_EXIT
+//sys  read(fd int, p *byte, np int) (n int, errno int)
+//sys  write(fd int, p *byte, np int) (n int, errno int)
+
+/*
+ * Unimplemented
+ */
+// AddKey
+// AfsSyscall
+// Alarm
+// ArchPrctl
+// Brk
+// Capget
+// Capset
+// ClockGetres
+// ClockGettime
+// ClockNanosleep
+// ClockSettime
+// Clone
+// CreateModule
+// DeleteModule
+// EpollCtlOld
+// EpollPwait
+// EpollWaitOld
+// Eventfd
+// Execve
+// Fadvise64
+// Fgetxattr
+// Flistxattr
+// Flock
+// Fork
+// Fremovexattr
+// Fsetxattr
+// Futex
+// GetKernelSyms
+// GetMempolicy
+// GetRobustList
+// GetThreadArea
+// Getitimer
+// Getpmsg
+// Getpriority
+// Getxattr
+// InotifyAddWatch
+// InotifyInit
+// InotifyRmWatch
+// IoCancel
+// IoDestroy
+// IoGetevents
+// IoSetup
+// IoSubmit
+// Ioctl
+// IoprioGet
+// IoprioSet
+// KexecLoad
+// Keyctl
+// Lgetxattr
+// Listxattr
+// Llistxattr
+// LookupDcookie
+// Lremovexattr
+// Lsetxattr
+// Madvise
+// Mbind
+// MigratePages
+// Mincore
+// Mlock
+// Mmap
+// ModifyLdt
+// Mount
+// MovePages
+// Mprotect
+// MqGetsetattr
+// MqNotify
+// MqOpen
+// MqTimedreceive
+// MqTimedsend
+// MqUnlink
+// Mremap
+// Msgctl
+// Msgget
+// Msgrcv
+// Msgsnd
+// Msync
+// Munlock
+// Munlockall
+// Munmap
+// Newfstatat
+// Nfsservctl
+// Personality
+// Poll
+// Ppoll
+// Prctl
+// Pselect6
+// Ptrace
+// Putpmsg
+// QueryModule
+// Quotactl
+// Readahead
+// Readv
+// Reboot
+// RemapFilePages
+// Removexattr
+// RequestKey
+// RestartSyscall
+// RtSigaction
+// RtSigpending
+// RtSigprocmask
+// RtSigqueueinfo
+// RtSigreturn
+// RtSigsuspend
+// RtSigtimedwait
+// SchedGetPriorityMax
+// SchedGetPriorityMin
+// SchedGetaffinity
+// SchedGetparam
+// SchedGetscheduler
+// SchedRrGetInterval
+// SchedSetaffinity
+// SchedSetparam
+// SchedYield
+// Security
+// Semctl
+// Semget
+// Semop
+// Semtimedop
+// Sendfile
+// SetMempolicy
+// SetRobustList
+// SetThreadArea
+// SetTidAddress
+// Setpriority
+// Setxattr
+// Shmat
+// Shmctl
+// Shmdt
+// Shmget
+// Sigaltstack
+// Signalfd
+// Swapoff
+// Swapon
+// Sysfs
+// TimerCreate
+// TimerDelete
+// TimerGetoverrun
+// TimerGettime
+// TimerSettime
+// Timerfd
+// Tkill (obsolete)
+// Tuxcall
+// Umount2
+// Uselib
+// Utimensat
+// Vfork
+// Vhangup
+// Vmsplice
+// Vserver
+// Waitid
+// Writev
+// _Sysctl
diff --git a/src/lib/syscall/syscall_linux_amd64.go b/src/lib/syscall/syscall_linux_amd64.go
new file mode 100644 (file)
index 0000000..8b3404d
--- /dev/null
@@ -0,0 +1,29 @@
+// 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
+
+import "syscall"
+
+func TimespecToNsec(ts Timespec) int64 {
+       return int64(ts.Sec)*1e9 + int64(ts.Nsec);
+}
+
+func NsecToTimespec(nsec int64) (ts Timespec) {
+       ts.Sec = nsec / 1e9;
+       ts.Nsec = 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 = nsec/1e9;
+       tv.Usec = nsec%1e9 / 1e3;
+       return;
+}
+
diff --git a/src/lib/syscall/types_darwin.c b/src/lib/syscall/types_darwin.c
new file mode 100644 (file)
index 0000000..65afd6c
--- /dev/null
@@ -0,0 +1,226 @@
+// 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.
+
+/*
+Input to godefs.  See PORT.
+ */
+
+#define __DARWIN_UNIX03 0
+#define KERNEL
+#define _DARWIN_USE_64_BIT_INODE
+#include <dirent.h>
+#include <fcntl.h>
+#include <mach/mach.h>
+#include <mach/message.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <sys/event.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/select.h>
+#include <sys/signal.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+// Machine characteristics; for internal use.
+
+enum
+{
+       $sizeofPtr = sizeof(void*),
+       $sizeofShort = sizeof(short),
+       $sizeofInt = sizeof(int),
+       $sizeofLong = sizeof(long),
+       $sizeofLongLong = sizeof(long long),
+};
+
+
+// Time
+
+typedef struct timespec $Timespec;
+typedef struct timeval $Timeval;
+
+// Processes
+
+typedef struct rusage $Rusage;
+typedef struct rlimit $Rlimit;
+
+typedef int $_C_int;
+typedef gid_t $_Gid_t;
+
+// Files
+
+enum
+{
+       $O_RDONLY = O_RDONLY,
+       $O_WRONLY = O_WRONLY,
+       $O_RDWR = O_RDWR,
+       $O_APPEND = O_APPEND,
+       $O_ASYNC = O_ASYNC,
+       $O_CREAT = O_CREAT,
+       $O_NOCTTY = O_NOCTTY,
+       $O_NONBLOCK = O_NONBLOCK,
+       $O_SYNC = O_SYNC,
+       $O_TRUNC = O_TRUNC,
+       $O_CLOEXEC = 0, // not supported
+
+       $F_GETFD = F_GETFD,
+       $F_SETFD = F_SETFD,
+
+       $F_GETFL = F_GETFL,
+       $F_SETFL = F_SETFL,
+
+       $FD_CLOEXEC = FD_CLOEXEC,
+
+       $NAME_MAX = NAME_MAX
+};
+
+enum
+{      // Directory mode bits
+       $S_IFMT = S_IFMT,
+       $S_IFIFO = S_IFIFO,
+       $S_IFCHR = S_IFCHR,
+       $S_IFDIR = S_IFDIR,
+       $S_IFBLK = S_IFBLK,
+       $S_IFREG = S_IFREG,
+       $S_IFLNK = S_IFLNK,
+       $S_IFSOCK = S_IFSOCK,
+       $S_IFWHT = S_IFWHT,
+       $S_ISUID = S_ISUID,
+       $S_ISGID = S_ISGID,
+       $S_ISVTX = S_ISVTX,
+       $S_IRUSR = S_IRUSR,
+       $S_IWUSR = S_IWUSR,
+       $S_IXUSR = S_IXUSR,
+};
+
+typedef struct stat64 $Stat_t;
+typedef struct statfs64 $Statfs_t;
+
+typedef struct dirent $Dirent;
+
+// Wait status.
+
+enum
+{
+       $WNOHANG = WNOHANG,
+       $WUNTRACED = WUNTRACED,
+       $WEXITED = WEXITED,
+       $WSTOPPED = WSTOPPED,
+       $WCONTINUED = WCONTINUED,
+       $WNOWAIT = WNOWAIT,
+};
+
+// Sockets
+
+enum
+{
+       $AF_UNIX = AF_UNIX,
+       $AF_INET = AF_INET,
+       $AF_DATAKIT = AF_DATAKIT,
+       $AF_INET6 = AF_INET6,
+
+       $SOCK_STREAM = SOCK_STREAM,
+       $SOCK_DGRAM = SOCK_DGRAM,
+       $SOCK_RAW = SOCK_RAW,
+       $SOCK_SEQPACKET = SOCK_SEQPACKET,
+
+       $SOL_SOCKET = SOL_SOCKET,
+
+       $SO_REUSEADDR = SO_REUSEADDR,
+       $SO_KEEPALIVE = SO_KEEPALIVE,
+       $SO_DONTROUTE = SO_DONTROUTE,
+       $SO_BROADCAST = SO_BROADCAST,
+       $SO_USELOOPBACK = SO_USELOOPBACK,
+       $SO_LINGER = SO_LINGER,
+       $SO_REUSEPORT = SO_REUSEPORT,
+       $SO_SNDBUF = SO_SNDBUF,
+       $SO_RCVBUF = SO_RCVBUF,
+       $SO_SNDTIMEO = SO_SNDTIMEO,
+       $SO_RCVTIMEO = SO_RCVTIMEO,
+       $SO_NOSIGPIPE = SO_NOSIGPIPE,
+
+       $IPPROTO_TCP = IPPROTO_TCP,
+       $IPPROTO_UDP = IPPROTO_UDP,
+
+       $TCP_NODELAY = TCP_NODELAY,
+
+       $SOMAXCONN = SOMAXCONN
+};
+
+typedef struct sockaddr_in $RawSockaddrInet4;
+typedef struct sockaddr_in6 $RawSockaddrInet6;
+typedef struct sockaddr_un $RawSockaddrUnix;
+typedef struct sockaddr $RawSockaddr;
+
+union sockaddr_all {
+       struct sockaddr s1;     // this one gets used for fields
+       struct sockaddr_in s2;  // these pad it out
+       struct sockaddr_in6 s3;
+};
+
+struct sockaddr_any {
+       struct sockaddr addr;
+       char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
+};
+
+enum {
+       $SizeofSockaddrInet4 = sizeof(struct sockaddr_in),
+       $SizeofSockaddrInet6 = sizeof(struct sockaddr_in6),
+       $SizeofSockaddrAny = sizeof(struct sockaddr_any),
+       $SizeofSockaddrUnix = sizeof(struct sockaddr_un),
+};
+
+typedef struct sockaddr_any $RawSockaddrAny;
+typedef socklen_t $_Socklen;
+typedef struct linger $Linger;
+
+// Events (kqueue, kevent)
+
+enum {
+       // filters
+       $EVFILT_READ = EVFILT_READ,
+       $EVFILT_WRITE = EVFILT_WRITE,
+       $EVFILT_AIO = EVFILT_AIO,
+       $EVFILT_VNODE = EVFILT_VNODE,
+       $EVFILT_PROC = EVFILT_PROC,
+       $EVFILT_SIGNAL = EVFILT_SIGNAL,
+       $EVFILT_TIMER = EVFILT_TIMER,
+       $EVFILT_MACHPORT = EVFILT_MACHPORT,
+       $EVFILT_FS = EVFILT_FS,
+
+       $EVFILT_SYSCOUNT = EVFILT_SYSCOUNT,
+
+       // actions
+       $EV_ADD = EV_ADD,
+       $EV_DELETE = EV_DELETE,
+       $EV_DISABLE = EV_DISABLE,
+       $EV_RECEIPT = EV_RECEIPT,
+
+       // flags
+       $EV_ONESHOT = EV_ONESHOT,
+       $EV_CLEAR = EV_CLEAR,
+       $EV_SYSFLAGS = EV_SYSFLAGS,
+       $EV_FLAG0 = EV_FLAG0,
+       $EV_FLAG1 = EV_FLAG1,
+
+       // returned values
+       $EV_EOF = EV_EOF,
+       $EV_ERROR = EV_ERROR,
+};
+
+typedef struct kevent $Kevent_t;
+
+// Select
+
+typedef fd_set $FdSet;
diff --git a/src/lib/syscall/types_darwin_amd64.c b/src/lib/syscall/types_darwin_amd64.c
new file mode 100644 (file)
index 0000000..71f98e4
--- /dev/null
@@ -0,0 +1,5 @@
+// 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.
+
+// Nothing to see here.
diff --git a/src/lib/syscall/types_linux.c b/src/lib/syscall/types_linux.c
new file mode 100644 (file)
index 0000000..261772e
--- /dev/null
@@ -0,0 +1,217 @@
+// 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.
+
+/*
+Input to godefs.  See PORT.
+ */
+
+#define __DARWIN_UNIX03 0
+#define KERNEL
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <sys/epoll.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/select.h>
+#include <sys/signal.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/sysinfo.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/timex.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <unistd.h>
+#include <ustat.h>
+#include <utime.h>
+
+// Machine characteristics; for internal use.
+
+enum
+{
+       $sizeofPtr = sizeof(void*),
+       $sizeofShort = sizeof(short),
+       $sizeofInt = sizeof(int),
+       $sizeofLong = sizeof(long),
+       $sizeofLongLong = sizeof(long long),
+       $PathMax = PATH_MAX,
+};
+
+
+// Time
+
+typedef struct timespec $Timespec;
+typedef struct timeval $Timeval;
+typedef struct timex $Timex;
+typedef time_t $Time_t;
+typedef struct tms $Tms;
+typedef struct utimbuf $Utimbuf;
+
+// Processes
+
+typedef struct rusage $Rusage;
+typedef struct rlimit $Rlimit;
+
+typedef int $_C_int;
+typedef gid_t $_Gid_t;
+
+// Files
+
+enum
+{
+       $O_RDONLY = O_RDONLY,
+       $O_WRONLY = O_WRONLY,
+       $O_RDWR = O_RDWR,
+       $O_APPEND = O_APPEND,
+       $O_ASYNC = O_ASYNC,
+       $O_CREAT = O_CREAT,
+       $O_NOCTTY = O_NOCTTY,
+       $O_NONBLOCK = O_NONBLOCK,
+       $O_SYNC = O_SYNC,
+       $O_TRUNC = O_TRUNC,
+       $O_CLOEXEC = 0, // not supported
+
+       $F_GETFD = F_GETFD,
+       $F_SETFD = F_SETFD,
+
+       $F_GETFL = F_GETFL,
+       $F_SETFL = F_SETFL,
+
+       $FD_CLOEXEC = FD_CLOEXEC,
+
+       $NAME_MAX = NAME_MAX
+};
+
+enum
+{      // Directory mode bits
+       $S_IFMT = S_IFMT,
+       $S_IFIFO = S_IFIFO,
+       $S_IFCHR = S_IFCHR,
+       $S_IFDIR = S_IFDIR,
+       $S_IFBLK = S_IFBLK,
+       $S_IFREG = S_IFREG,
+       $S_IFLNK = S_IFLNK,
+       $S_IFSOCK = S_IFSOCK,
+       $S_ISUID = S_ISUID,
+       $S_ISGID = S_ISGID,
+       $S_ISVTX = S_ISVTX,
+       $S_IRUSR = S_IRUSR,
+       $S_IWUSR = S_IWUSR,
+       $S_IXUSR = S_IXUSR,
+};
+
+typedef struct stat $Stat_t;
+typedef struct statfs $Statfs_t;
+
+typedef struct dirent $Dirent;
+
+// Wait status.
+
+enum
+{
+       $WNOHANG = WNOHANG,
+       $WUNTRACED = WUNTRACED,
+       $WEXITED = WEXITED,
+       $WSTOPPED = WSTOPPED,
+       $WCONTINUED = WCONTINUED,
+       $WNOWAIT = WNOWAIT,
+};
+
+// Sockets
+
+enum
+{
+       $AF_UNIX = AF_UNIX,
+       $AF_INET = AF_INET,
+       $AF_INET6 = AF_INET6,
+
+       $SOCK_STREAM = SOCK_STREAM,
+       $SOCK_DGRAM = SOCK_DGRAM,
+       $SOCK_RAW = SOCK_RAW,
+       $SOCK_SEQPACKET = SOCK_SEQPACKET,
+
+       $SOL_SOCKET = SOL_SOCKET,
+
+       $SO_REUSEADDR = SO_REUSEADDR,
+       $SO_KEEPALIVE = SO_KEEPALIVE,
+       $SO_DONTROUTE = SO_DONTROUTE,
+       $SO_BROADCAST = SO_BROADCAST,
+       $SO_LINGER = SO_LINGER,
+       $SO_SNDBUF = SO_SNDBUF,
+       $SO_RCVBUF = SO_RCVBUF,
+       $SO_SNDTIMEO = SO_SNDTIMEO,
+       $SO_RCVTIMEO = SO_RCVTIMEO,
+
+       $IPPROTO_TCP = IPPROTO_TCP,
+       $IPPROTO_UDP = IPPROTO_UDP,
+
+       $TCP_NODELAY = TCP_NODELAY,
+
+       $SOMAXCONN = SOMAXCONN
+};
+
+typedef struct sockaddr_in $RawSockaddrInet4;
+typedef struct sockaddr_in6 $RawSockaddrInet6;
+typedef struct sockaddr_un $RawSockaddrUnix;
+typedef struct sockaddr $RawSockaddr;
+
+union sockaddr_all {
+       struct sockaddr s1;     // this one gets used for fields
+       struct sockaddr_in s2;  // these pad it out
+       struct sockaddr_in6 s3;
+};
+
+struct sockaddr_any {
+       struct sockaddr addr;
+       char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
+};
+
+enum {
+       $SizeofSockaddrInet4 = sizeof(struct sockaddr_in),
+       $SizeofSockaddrInet6 = sizeof(struct sockaddr_in6),
+       $SizeofSockaddrAny = sizeof(struct sockaddr_any),
+       $SizeofSockaddrUnix = sizeof(struct sockaddr_un),
+};
+
+typedef struct sockaddr_any $RawSockaddrAny;
+typedef socklen_t $_Socklen;
+typedef struct linger $Linger;
+
+// Misc
+
+enum {
+       $EPOLLIN = EPOLLIN,
+       $EPOLLRDHUP = EPOLLRDHUP,
+       $EPOLLOUT = EPOLLOUT,
+       $EPOLLONESHOT = EPOLLONESHOT,
+       $EPOLL_CTL_MOD = EPOLL_CTL_MOD,
+       $EPOLL_CTL_ADD = EPOLL_CTL_ADD,
+       $EPOLL_CTL_DEL = EPOLL_CTL_DEL,
+};
+
+typedef fd_set $FdSet;
+typedef struct sysinfo $Sysinfo_t;
+typedef struct utsname $Utsname;
+typedef struct ustat $Ustat_t;
+
+// The real epoll_event is a union, and godefs doesn't handle it well.
+struct my_epoll_event {
+       uint32_t events;
+       int32_t fd;
+       int32_t pad;
+};
+
+typedef struct my_epoll_event $EpollEvent;
diff --git a/src/lib/syscall/types_linux_amd64.c b/src/lib/syscall/types_linux_amd64.c
new file mode 100644 (file)
index 0000000..37ce7d7
--- /dev/null
@@ -0,0 +1,5 @@
+// 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.
+
+// Nothing to see here