diff --git a/src/lib/syscall/PORT b/src/lib/syscall/PORT new file mode 100755 index 0000000000..2f0fe147be --- /dev/null +++ b/src/lib/syscall/PORT @@ -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 index 0000000000..67a529d347 --- /dev/null +++ b/src/lib/syscall/errstr.go @@ -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] +} + diff --git a/src/lib/syscall/exec.go b/src/lib/syscall/exec.go index 63d7821089..58fb058635 100644 --- a/src/lib/syscall/exec.go +++ b/src/lib/syscall/exec.go @@ -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; - } - return r1, err1; +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 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 index 0000000000..015f021457 --- /dev/null +++ b/src/lib/syscall/mkerrors @@ -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 ' | + # 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 ' | + 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 ' + echo '#include ' + 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 +#include +#include +#include + +#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 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 index 0000000000..20b5c26bf5 --- /dev/null +++ b/src/lib/syscall/mksyscall @@ -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 <){ + 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 < 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 index 0000000000..2f576ad631 --- /dev/null +++ b/src/lib/syscall/syscall_darwin_amd64.go @@ -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 index 0000000000..e89c9bcb62 --- /dev/null +++ b/src/lib/syscall/syscall_linux.go @@ -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 index 0000000000..8b3404d3e3 --- /dev/null +++ b/src/lib/syscall/syscall_linux_amd64.go @@ -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 index 0000000000..65afd6ca6c --- /dev/null +++ b/src/lib/syscall/types_darwin.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// 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 index 0000000000..71f98e413e --- /dev/null +++ b/src/lib/syscall/types_darwin_amd64.c @@ -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 index 0000000000..261772eac2 --- /dev/null +++ b/src/lib/syscall/types_linux.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// 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 index 0000000000..37ce7d76e9 --- /dev/null +++ b/src/lib/syscall/types_linux_amd64.c @@ -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