URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/tags/gnu-dev/fsf-gcc-snapshot-1-mar-12/or1k-gcc/libgo/go/syscall
- from Rev 747 to Rev 783
- ↔ Reverse comparison
Rev 747 → Rev 783
/exec_bsd.go
0,0 → 1,223
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// +build darwin freebsd netbsd openbsd |
|
package syscall |
|
import ( |
"unsafe" |
) |
|
type SysProcAttr struct { |
Chroot string // Chroot. |
Credential *Credential // Credential. |
Ptrace bool // Enable tracing. |
Setsid bool // Create session. |
Setpgid bool // Set process group ID to new pid (SYSV setpgrp) |
Setctty bool // Set controlling terminal to fd 0 |
Noctty bool // Detach fd 0 from controlling terminal |
} |
|
// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child. |
// If a dup or exec fails, write the errno error to pipe. |
// (Pipe is close-on-exec so if exec succeeds, it will be closed.) |
// In the child, this function must not acquire any locks, because |
// they might have been locked at the time of the fork. This means |
// no rescheduling, no malloc calls, and no new stack segments. |
// The calls to RawSyscall are okay because they are assembly |
// functions that do not grow the stack. |
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) { |
// Declare all variables at top in case any |
// declarations require heap allocation (e.g., err1). |
var ( |
r1 Pid_t |
err1 Errno |
nextfd int |
i int |
) |
|
// guard against side effects of shuffling fds below. |
fd := append([]int(nil), attr.Files...) |
|
// About to call fork. |
// No more allocation or calls of non-assembly functions. |
r1, err1 = raw_fork() |
if err1 != 0 { |
return 0, err1 |
} |
|
if r1 != 0 { |
// parent; return PID |
return int(r1), 0 |
} |
|
// Fork succeeded, now in child. |
|
// Enable tracing if requested. |
if sys.Ptrace { |
err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil) |
if err1 != 0 { |
goto childerror |
} |
} |
|
// Session ID |
if sys.Setsid { |
err1 = raw_setsid() |
if err1 != 0 { |
goto childerror |
} |
} |
|
// Set process group |
if sys.Setpgid { |
err1 = raw_setpgid(0, 0) |
if err1 != 0 { |
goto childerror |
} |
} |
|
// Chroot |
if chroot != nil { |
err1 = raw_chroot(chroot) |
if err1 != 0 { |
goto childerror |
} |
} |
|
// User and groups |
if cred := sys.Credential; cred != nil { |
ngroups := len(cred.Groups) |
if ngroups == 0 { |
err2 := setgroups(0, nil) |
if err2 == nil { |
err1 = 0 |
} else { |
err1 = err2.(Errno) |
} |
} else { |
groups := make([]Gid_t, ngroups) |
for i, v := range cred.Groups { |
groups[i] = Gid_t(v) |
} |
err2 := setgroups(ngroups, &groups[0]) |
if err2 == nil { |
err1 = 0 |
} else { |
err1 = err2.(Errno) |
} |
} |
if err1 != 0 { |
goto childerror |
} |
err2 := Setgid(int(cred.Gid)) |
if err2 != nil { |
err1 = err2.(Errno) |
goto childerror |
} |
err2 = Setuid(int(cred.Uid)) |
if err2 != nil { |
err1 = err2.(Errno) |
goto childerror |
} |
} |
|
// Chdir |
if dir != nil { |
err1 = raw_chdir(dir) |
if err1 != 0 { |
goto childerror |
} |
} |
|
// Pass 1: look for fd[i] < i and move those up above len(fd) |
// so that pass 2 won't stomp on an fd it needs later. |
nextfd = int(len(fd)) |
if pipe < nextfd { |
err1 = raw_dup2(pipe, nextfd) |
if err1 != 0 { |
goto childerror |
} |
raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC) |
pipe = nextfd |
nextfd++ |
} |
for i = 0; i < len(fd); i++ { |
if fd[i] >= 0 && fd[i] < int(i) { |
err1 = raw_dup2(fd[i], nextfd) |
if err1 != 0 { |
goto childerror |
} |
raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC) |
fd[i] = nextfd |
nextfd++ |
if nextfd == pipe { // don't stomp on pipe |
nextfd++ |
} |
} |
} |
|
// Pass 2: dup fd[i] down onto i. |
for i = 0; i < len(fd); i++ { |
if fd[i] == -1 { |
raw_close(i) |
continue |
} |
if fd[i] == int(i) { |
// dup2(i, i) won't clear close-on-exec flag on Linux, |
// probably not elsewhere either. |
_, err1 = raw_fcntl(fd[i], F_SETFD, 0) |
if err1 != 0 { |
goto childerror |
} |
continue |
} |
// The new fd is created NOT close-on-exec, |
// which is exactly what we want. |
err1 = raw_dup2(fd[i], i) |
if err1 != 0 { |
goto childerror |
} |
} |
|
// By convention, we don't close-on-exec the fds we are |
// started with, so if len(fd) < 3, close 0, 1, 2 as needed. |
// Programs that know they inherit fds >= 3 will need |
// to set them close-on-exec. |
for i = len(fd); i < 3; i++ { |
raw_close(i) |
} |
|
// Detach fd 0 from tty |
if sys.Noctty { |
_, err1 = raw_ioctl(0, TIOCNOTTY, 0) |
if err1 != 0 { |
goto childerror |
} |
} |
|
// Make fd 0 the tty |
if sys.Setctty { |
_, err1 = raw_ioctl(0, TIOCSCTTY, 0) |
if err1 != 0 { |
goto childerror |
} |
} |
|
// Time to exec. |
err1 = raw_execve(argv0, &argv[0], &envv[0]) |
|
childerror: |
// send error code on pipe |
raw_write(pipe, (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1))) |
for { |
raw_exit(253) |
} |
|
// Calling panic is not actually safe, |
// but the for loop above won't break |
// and this shuts up the compiler. |
panic("unreached") |
} |
/sockcmsg_unix.go
0,0 → 1,115
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// +build darwin freebsd linux netbsd openbsd |
|
// Socket control messages |
|
package syscall |
|
import ( |
"unsafe" |
) |
|
// Round the length of a raw sockaddr up to align it propery. |
func cmsgAlignOf(salen int) int { |
salign := int(sizeofPtr) |
// NOTE: It seems like 64-bit Darwin kernel still requires 32-bit |
// aligned access to BSD subsystem. |
if darwinAMD64 { |
salign = 4 |
} |
if salen == 0 { |
return salign |
} |
return (salen + salign - 1) & ^(salign - 1) |
} |
|
// CmsgLen returns the value to store in the Len field of the Cmsghdr |
// structure, taking into account any necessary alignment. |
func CmsgLen(datalen int) int { |
return cmsgAlignOf(SizeofCmsghdr) + datalen |
} |
|
// CmsgSpace returns the number of bytes an ancillary element with |
// payload of the passed data length occupies. |
func CmsgSpace(datalen int) int { |
return cmsgAlignOf(SizeofCmsghdr) + cmsgAlignOf(datalen) |
} |
|
func cmsgData(cmsg *Cmsghdr) unsafe.Pointer { |
return unsafe.Pointer(uintptr(unsafe.Pointer(cmsg)) + uintptr(SizeofCmsghdr)) |
} |
|
type SocketControlMessage struct { |
Header Cmsghdr |
Data []byte |
} |
|
func ParseSocketControlMessage(buf []byte) ([]SocketControlMessage, error) { |
var ( |
h *Cmsghdr |
dbuf []byte |
e error |
cmsgs []SocketControlMessage |
) |
|
for len(buf) >= CmsgLen(0) { |
h, dbuf, e = socketControlMessageHeaderAndData(buf) |
if e != nil { |
break |
} |
m := SocketControlMessage{} |
m.Header = *h |
m.Data = dbuf[:int(h.Len)-cmsgAlignOf(SizeofCmsghdr)] |
cmsgs = append(cmsgs, m) |
buf = buf[cmsgAlignOf(int(h.Len)):] |
} |
|
return cmsgs, e |
} |
|
func socketControlMessageHeaderAndData(buf []byte) (*Cmsghdr, []byte, error) { |
h := (*Cmsghdr)(unsafe.Pointer(&buf[0])) |
if int(h.Len) < SizeofCmsghdr || int(h.Len) > len(buf) { |
return nil, nil, EINVAL |
} |
return h, buf[cmsgAlignOf(SizeofCmsghdr):], nil |
} |
|
// UnixRights encodes a set of open file descriptors into a socket |
// control message for sending to another process. |
func UnixRights(fds ...int) []byte { |
datalen := len(fds) * 4 |
buf := make([]byte, CmsgSpace(datalen)) |
cmsg := (*Cmsghdr)(unsafe.Pointer(&buf[0])) |
cmsg.Level = SOL_SOCKET |
cmsg.Type = SCM_RIGHTS |
cmsg.SetLen(CmsgLen(datalen)) |
|
data := uintptr(cmsgData(cmsg)) |
for _, fd := range fds { |
*(*int32)(unsafe.Pointer(data)) = int32(fd) |
data += 4 |
} |
|
return buf |
} |
|
// ParseUnixRights decodes a socket control message that contains an |
// integer array of open file descriptors from another process. |
func ParseUnixRights(msg *SocketControlMessage) ([]int, error) { |
if msg.Header.Level != SOL_SOCKET { |
return nil, EINVAL |
} |
if msg.Header.Type != SCM_RIGHTS { |
return nil, EINVAL |
} |
fds := make([]int, len(msg.Data)>>2) |
for i, j := 0, 0; i < len(msg.Data); i += 4 { |
fds[j] = int(*(*int32)(unsafe.Pointer(&msg.Data[i]))) |
j++ |
} |
return fds, nil |
} |
/libcall_linux_amd64.go
0,0 → 1,13
// Copyright 2012 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// GNU/Linux library calls amd64 specific. |
|
package syscall |
|
//sys Ioperm(from int, num int, on int) (err error) |
//ioperm(from _C_long, num _C_long, on int) int |
|
//sys Iopl(level int) (err error) |
//iopl(level int) int |
/syscall_errno.go
0,0 → 1,26
// 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 |
|
// An Errno is an unsigned number describing an error condition. |
// It implements the error interface. The zero Errno is by convention |
// a non-error, so code to convert from Errno to error should use: |
// err = nil |
// if errno != 0 { |
// err = errno |
// } |
type Errno uintptr |
|
func (e Errno) Error() string { |
return Errstr(int(e)) |
} |
|
func (e Errno) Temporary() bool { |
return e == EINTR || e == EMFILE || e.Timeout() |
} |
|
func (e Errno) Timeout() bool { |
return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT |
} |
/mksyscall.awk
0,0 → 1,264
# Copyright 2011 The Go Authors. All rights reserved. |
# Use of this source code is governed by a BSD-style |
# license that can be found in the LICENSE file. |
|
# This AWK script reads a Go file with comments describing syscall |
# functions and the C routines they map to. It generates the Go code |
# which calls the C routines. |
|
# The syscall functins are marked by lines beginning with "//sys" and |
# read like func declarations if //sys is replaced by func, but: |
# * The parameter lists must give a name for each argument. |
# This includes return parameters. |
# * The parameter lists must give a type for each argument: |
# the (x, y, z int) shorthand is not allowed. |
# * If the return parameter is an error, it must be named err. |
|
# A line beginning with //sysnb is like //sys, except that the |
# goroutine will not be suspended during the execution of the library |
# call. This must only be used for library calls which can never |
# block, as otherwise the library call could cause all goroutines to |
# hang. |
|
# After the //sys or //sysnb line comes a second line which describes |
# the C function. The name must be the name of the function in the C |
# library, and may be the same as the Go function. The limitations on |
# the argument list are the same as for the //sys line, but there must |
# be at most one result parameter, and it must be given as just a |
# type, without a name. |
|
BEGIN { |
print "// This file was automatically generated by mksyscall.awk" |
print "" |
print "package syscall" |
print "" |
print "import \"unsafe\"" |
print "" |
status = 0 |
} |
|
/^\/\/sys/ { |
if ($1 == "//sysnb") { |
blocking = 0 |
} else { |
blocking = 1 |
} |
|
line = $0 |
|
if (match(line, "//sys(nb)?[ ]*[a-zA-Z0-9_]+\\([^()]*\\) *(\\(([^()]+)\\))?") == 0) { |
print "unmatched line:", $0 | "cat 1>&2" |
status = 1 |
next |
} |
|
# Sets a[1] = //sysnb, a[2] == function name. |
split(line, a, "[ (]*") |
gofnname = a[2] |
|
off = match(line, "\\([^()]*\\)") |
end = index(substr(line, off, length(line) - off + 1), ")") |
gofnparams = substr(line, off + 1, end - 2) |
|
line = substr(line, off + end, length(line) - (off + end) + 1) |
off = match(line, "\\([^()]*\\)") |
if (off == 0) { |
gofnresults = "" |
} else { |
end = index(substr(line, off, length(line) - off + 1), ")") |
gofnresults = substr(line, off + 1, end - 2) |
} |
|
getline |
line = $0 |
|
if (match(line, "//[a-zA-Z0-9_]+\\([^()]*\\)") == 0) { |
print "unmatched C line", $0, "after", gofnname | "cat 1>&2" |
status = 1 |
next |
} |
|
split(line, a, "[ (]*") |
cfnname = substr(a[1], 3, length(a[1]) - 2) |
|
off = match(line, "\\([^()]*\\)") |
end = index(substr(line, off, length(line) - off + 1), ")") |
cfnparams = substr(line, off + 1, end - 2) |
|
line = substr(line, off + end + 1, length(line) - (off + end) + 1) |
while (substr(line, 1, 1) == " ") { |
line = substr(line, 2, length(line) - 1) |
} |
end = index(line, " ") |
if (end != 0) { |
line = substr(line, 1, end) |
} |
cfnresult = line |
|
printf("// Automatically generated wrapper for %s/%s\n", gofnname, cfnname) |
printf("//extern %s\n", cfnname) |
printf("func c_%s(%s) %s\n", cfnname, cfnparams, cfnresult) |
printf("func %s(%s) %s%s%s%s{\n", |
gofnname, gofnparams, gofnresults == "" ? "" : "(", gofnresults, |
gofnresults == "" ? "" : ")", gofnresults == "" ? "" : " ") |
|
loc = gofnname "/" cfnname ":" |
|
split(gofnparams, goargs, ", *") |
split(cfnparams, cargs, ", *") |
args = "" |
carg = 1 |
for (goarg = 1; goargs[goarg] != ""; goarg++) { |
if (cargs[carg] == "") { |
print loc, "not enough C parameters" |
} |
|
if (args != "") { |
args = args ", " |
} |
|
if (split(goargs[goarg], a) != 2) { |
print loc, "bad parameter:", goargs[goarg] | "cat 1>&2" |
status = 1 |
next |
} |
|
goname = a[1] |
gotype = a[2] |
|
if (split(cargs[carg], a) != 2) { |
print loc, "bad C parameter:", cargs[carg] | "cat 1>&2" |
status = 1 |
next |
} |
|
ctype = a[2] |
|
if (gotype ~ /^\*/) { |
if (gotype != ctype) { |
print loc, "Go/C pointer type mismatch:", gotype, ctype | "cat 1>&2" |
status = 1 |
next |
} |
args = args goname |
} else if (gotype == "string") { |
if (ctype != "*byte") { |
print loc, "Go string not matched to C *byte:", gotype, ctype | "cat 1>&2" |
status = 1 |
next |
} |
printf("\t_p%d := StringBytePtr(%s)\n", goarg, goname) |
args = sprintf("%s_p%d", args, goarg) |
} else if (gotype ~ /^\[\](.*)/) { |
if (ctype !~ /^\*/ || cargs[carg + 1] == "") { |
print loc, "bad C type for slice:", gotype, ctype | "cat 1>&2" |
status = 1 |
next |
} |
|
# Convert a slice into a pair of pointer, length. |
# Don't try to take the address of the zeroth element of a |
# nil slice. |
printf("\tvar _p%d %s\n", goarg, ctype) |
printf("\tif len(%s) > 0 {\n", goname) |
printf("\t\t_p%d = (%s)(unsafe.Pointer(&%s[0]))\n", goarg, ctype, goname) |
printf("\t} else {\n") |
printf("\t\t_p%d = (%s)(unsafe.Pointer(&_zero))\n", goarg, ctype) |
printf("\t}\n") |
|
++carg |
if (split(cargs[carg], cparam) != 2) { |
print loc, "bad C parameter:", cargs[carg] | "cat 1>&2" |
status = 1 |
next |
} |
|
args = sprintf("%s_p%d, %s(len(%s))", args, goarg, cparam[2], goname) |
} else if (gotype == "uintptr" && ctype ~ /^\*/) { |
args = sprintf("%s(%s)(unsafe.Pointer(%s))", args, ctype, goname) |
} else { |
args = sprintf("%s%s(%s)", args, ctype, goname) |
} |
|
carg++ |
} |
|
if (cargs[carg] != "") { |
print loc, "too many C parameters" | "cat 1>&2" |
status = 1 |
next |
} |
|
if (blocking) { |
print "\tentersyscall()" |
} |
|
printf("\t") |
if (gofnresults != "") { |
printf("_r := ") |
} |
printf("c_%s(%s)\n", cfnname, args) |
|
if (gofnresults != "") { |
fields = split(gofnresults, goresults, ", *") |
if (fields > 2) { |
print loc, "too many Go results" | "cat 1>&2" |
status = 1 |
next |
} |
usedr = 0 |
for (goresult = 1; goresults[goresult] != ""; goresult++) { |
if (split(goresults[goresult], goparam) != 2) { |
print loc, "bad result:", goresults[goresult] | "cat 1>&2" |
status = 1 |
next |
} |
|
goname = goparam[1] |
gotype = goparam[2] |
|
if (goname == "err") { |
if (cfnresult ~ /^\*/) { |
print "\tif _r == nil {" |
} else { |
print "\tif _r < 0 {" |
} |
print "\t\terr = GetErrno()" |
print "\t}" |
} else if (gotype == "uintptr" && cfnresult ~ /^\*/) { |
printf("\t%s = (%s)(unsafe.Pointer(_r))\n", goname, gotype) |
} else { |
if (usedr) { |
print loc, "two parameters but no errno parameter" | "cat 1>&2" |
status = 1 |
next |
} |
printf("\t%s = (%s)(_r)\n", goname, gotype) |
usedr = 1 |
} |
} |
} |
|
if (blocking) { |
print "\texitsyscall()" |
} |
|
if (gofnresults != "") { |
print "\treturn" |
} |
|
print "}" |
|
print "" |
|
next |
} |
|
{ next } |
|
END { |
if (status != 0) { |
print "*** mksyscall.awk failed" | "cat 1>&2" |
exit status |
} |
} |
/socket_bsd.go
0,0 → 1,78
// socket_bsd.go -- Socket handling specific to *BSD based systems. |
|
// Copyright 2010 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
const SizeofSockaddrInet4 = 16 |
const SizeofSockaddrInet6 = 28 |
const SizeofSockaddrUnix = 110 |
|
type RawSockaddrInet4 struct { |
Len uint8; |
Family uint8; |
Port uint16; |
Addr [4]byte /* in_addr */; |
Zero [8]uint8; |
} |
|
func (sa *RawSockaddrInet4) setLen() Socklen_t { |
sa.Len = SizeofSockaddrInet4 |
return SizeofSockaddrInet4 |
} |
|
type RawSockaddrInet6 struct { |
Len uint8; |
Family uint8; |
Port uint16; |
Flowinfo uint32; |
Addr [16]byte /* in6_addr */; |
Scope_id uint32; |
} |
|
func (sa *RawSockaddrInet6) setLen() Socklen_t { |
sa.Len = SizeofSockaddrInet6 |
return SizeofSockaddrInet6 |
} |
|
type RawSockaddrUnix struct { |
Len uint8; |
Family uint8; |
Path [108]int8; |
} |
|
func (sa *RawSockaddrUnix) setLen(n int) { |
sa.Len = uint8(3 + n) // 2 for Family, Len; 1 for NUL. |
} |
|
func (sa *RawSockaddrUnix) getLen() (int, error) { |
if sa.Len < 3 || sa.Len > SizeofSockaddrUnix { |
return 0, EINVAL |
} |
n := int(sa.Len) - 3 // subtract leading Family, Len, terminating NUL. |
for i := 0; i < n; i++ { |
if sa.Path[i] == 0 { |
// found early NUL; assume Len is overestimating. |
n = i |
break |
} |
} |
return n, nil |
} |
|
type RawSockaddr struct { |
Len uint8; |
Family uint8; |
Data [14]int8; |
} |
|
// BindToDevice binds the socket associated with fd to device. |
func BindToDevice(fd int, device string) (err error) { |
return ENOSYS |
} |
|
func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, error) { |
return nil, EAFNOSUPPORT |
} |
/libcall_linux_386.go
0,0 → 1,13
// Copyright 2012 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// GNU/Linux library calls 386 specific. |
|
package syscall |
|
//sys Ioperm(from int, num int, on int) (err error) |
//ioperm(from _C_long, num _C_long, on int) int |
|
//sys Iopl(level int) (err error) |
//iopl(level int) int |
/wait.c
0,0 → 1,104
/* wait.c -- functions for getting wait status values. |
|
Copyright 2011 The Go Authors. All rights reserved. |
Use of this source code is governed by a BSD-style |
license that can be found in the LICENSE file. |
|
We use C code to extract the wait status so that we can easily be |
OS-independent. */ |
|
#include <stdint.h> |
#include <sys/wait.h> |
|
extern _Bool Exited (uint32_t *w) |
__asm__ ("libgo_syscall.syscall.Exited.N32_libgo_syscall.syscall.WaitStatus"); |
|
_Bool |
Exited (uint32_t *w) |
{ |
return WIFEXITED (*w) != 0; |
} |
|
extern _Bool Signaled (uint32_t *w) |
__asm__ ("libgo_syscall.syscall.Signaled.N32_libgo_syscall.syscall.WaitStatus"); |
|
_Bool |
Signaled (uint32_t *w) |
{ |
return WIFSIGNALED (*w) != 0; |
} |
|
extern _Bool Stopped (uint32_t *w) |
__asm__ ("libgo_syscall.syscall.Stopped.N32_libgo_syscall.syscall.WaitStatus"); |
|
_Bool |
Stopped (uint32_t *w) |
{ |
return WIFSTOPPED (*w) != 0; |
} |
|
extern _Bool Continued (uint32_t *w) |
__asm__ ("libgo_syscall.syscall.Continued.N32_libgo_syscall.syscall.WaitStatus"); |
|
_Bool |
Continued (uint32_t *w) |
{ |
return WIFCONTINUED (*w) != 0; |
} |
|
extern _Bool CoreDump (uint32_t *w) |
__asm__ ("libgo_syscall.syscall.CoreDump.N32_libgo_syscall.syscall.WaitStatus"); |
|
_Bool |
CoreDump (uint32_t *w) |
{ |
return WCOREDUMP (*w) != 0; |
} |
|
extern int ExitStatus (uint32_t *w) |
__asm__ ("libgo_syscall.syscall.ExitStatus.N32_libgo_syscall.syscall.WaitStatus"); |
|
int |
ExitStatus (uint32_t *w) |
{ |
if (!WIFEXITED (*w)) |
return -1; |
return WEXITSTATUS (*w); |
} |
|
extern int Signal (uint32_t *w) |
__asm__ ("libgo_syscall.syscall.Signal.N32_libgo_syscall.syscall.WaitStatus"); |
|
int |
Signal (uint32_t *w) |
{ |
if (!WIFSIGNALED (*w)) |
return -1; |
return WTERMSIG (*w); |
} |
|
extern int StopSignal (uint32_t *w) |
__asm__ ("libgo_syscall.syscall.StopSignal.N32_libgo_syscall.syscall.WaitStatus"); |
|
int |
StopSignal (uint32_t *w) |
{ |
if (!WIFSTOPPED (*w)) |
return -1; |
return WSTOPSIG (*w); |
} |
|
extern int TrapCause (uint32_t *w) |
__asm__ ("libgo_syscall.syscall.TrapCause.N32_libgo_syscall.syscall.WaitStatus"); |
|
int |
TrapCause (uint32_t *w __attribute__ ((unused))) |
{ |
#ifndef __linux__ |
return -1; |
#else |
if (!WIFSTOPPED (*w) || WSTOPSIG (*w) != SIGTRAP) |
return -1; |
return *w >> 16; |
#endif |
} |
/sleep_rtems.go
0,0 → 1,13
// sleep_rtems.go -- Sleep on RTEMS. |
|
// Copyright 2010 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
func Sleep(nsec int64) (err error) { |
ts := NsecToTimespec(nsec) |
err = Nanosleep(&ts, nil) |
return |
} |
/socket_irix.go
0,0 → 1,130
// socket_irix.go -- Socket handling specific to IRIX 6. |
|
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
const SizeofSockaddrInet4 = 16 |
const SizeofSockaddrInet6 = 28 |
const SizeofSockaddrUnix = 110 |
|
type RawSockaddrInet4 struct { |
Family uint16 |
Port uint16 |
Addr [4]byte /* in_addr */ |
Zero [8]uint8 |
} |
|
func (sa *RawSockaddrInet4) setLen() Socklen_t { |
return SizeofSockaddrInet4 |
} |
|
type RawSockaddrInet6 struct { |
Family uint16 |
Port uint16 |
Flowinfo uint32 |
Addr [16]byte /* in6_addr */ |
Scope_id uint32 |
} |
|
func (sa *RawSockaddrInet6) setLen() Socklen_t { |
return SizeofSockaddrInet6 |
} |
|
type RawSockaddrUnix struct { |
Family uint16 |
Path [108]int8 |
} |
|
func (sa *RawSockaddrUnix) setLen(int) { |
} |
|
func (sa *RawSockaddrUnix) getLen() (int, error) { |
if sa.Path[0] == 0 { |
// "Abstract" Unix domain socket. |
// Rewrite leading NUL as @ for textual display. |
// (This is the standard convention.) |
// Not friendly to overwrite in place, |
// but the callers below don't care. |
sa.Path[0] = '@' |
} |
|
// Assume path ends at NUL. |
// This is not technically the GNU/Linux semantics for |
// abstract Unix domain sockets--they are supposed |
// to be uninterpreted fixed-size binary blobs--but |
// everyone uses this convention. |
n := 0 |
for n < len(sa.Path)-3 && sa.Path[n] != 0 { |
n++ |
} |
|
return n, nil |
} |
|
type RawSockaddr struct { |
Family uint16 |
Data [14]int8 |
} |
|
// BindToDevice binds the socket associated with fd to device. |
func BindToDevice(fd int, device string) (err error) { |
return ENOSYS |
} |
|
// <netdb.h> only provides struct addrinfo, AI_* and EAI_* if _NO_XOPEN4 |
// && _NO_XOPEN5, but -D_XOPEN_SOURCE=500 is required for msg_control etc. |
// in struct msghgr, so simply provide them here. |
type Addrinfo struct { |
Ai_flags int32 |
Ai_family int32 |
Ai_socktype int32 |
Ai_protocol int32 |
Ai_addrlen int32 |
Ai_canonname *uint8 |
Ai_addr *_sockaddr |
Ai_next *Addrinfo |
} |
|
const ( |
AI_PASSIVE = 0x00000001 |
AI_CANONNAME = 0x00000002 |
AI_NUMERICHOST = 0x00000004 |
AI_NUMERICSERV = 0x00000008 |
AI_ALL = 0x00000100 |
AI_ADDRCONFIG = 0x00000400 |
AI_V4MAPPED = 0x00000800 |
AI_DEFAULT = (AI_V4MAPPED | AI_ADDRCONFIG) |
) |
|
const ( |
EAI_ADDRFAMILY = 1 |
EAI_AGAIN = 2 |
EAI_BADFLAGS = 3 |
EAI_FAIL = 4 |
EAI_FAMILY = 5 |
EAI_MEMORY = 6 |
EAI_NODATA = 7 |
EAI_NONAME = 8 |
EAI_SERVICE = 9 |
EAI_SOCKTYPE = 10 |
EAI_SYSTEM = 11 |
EAI_BADHINTS = 12 |
EAI_OVERFLOW = 13 |
EAI_MAX = 14 |
) |
|
func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, error) { |
return nil, EAFNOSUPPORT |
} |
|
// <netinet/in.h.h> only provides IPV6_* etc. if _NO_XOPEN4 && _NO_XOPEN5, |
// so as above simply provide them here. |
const ( |
IPV6_UNICAST_HOPS = 48 |
IPV6_MULTICAST_IF = IP_MULTICAST_IF |
IPV6_MULTICAST_HOPS = IP_MULTICAST_TTL |
IPV6_MULTICAST_LOOP = IP_MULTICAST_LOOP |
) |
/socket_solaris.go
0,0 → 1,80
// socket_solaris.go -- Socket handling specific to Solaris. |
|
// Copyright 2010 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
const SizeofSockaddrInet4 = 16 |
const SizeofSockaddrInet6 = 32 |
const SizeofSockaddrUnix = 110 |
|
type RawSockaddrInet4 struct { |
Family uint16 |
Port uint16 |
Addr [4]byte /* in_addr */ |
Zero [8]uint8 |
} |
|
func (sa *RawSockaddrInet4) setLen() Socklen_t { |
return SizeofSockaddrInet4 |
} |
|
type RawSockaddrInet6 struct { |
Family uint16 |
Port uint16 |
Flowinfo uint32 |
Addr [16]byte /* in6_addr */ |
Scope_id uint32 |
Src_id uint32 |
} |
|
func (sa *RawSockaddrInet6) setLen() Socklen_t { |
return SizeofSockaddrInet6 |
} |
|
type RawSockaddrUnix struct { |
Family uint16 |
Path [108]int8 |
} |
|
func (sa *RawSockaddrUnix) setLen(int) { |
} |
|
func (sa *RawSockaddrUnix) getLen() (int, error) { |
if sa.Path[0] == 0 { |
// "Abstract" Unix domain socket. |
// Rewrite leading NUL as @ for textual display. |
// (This is the standard convention.) |
// Not friendly to overwrite in place, |
// but the callers below don't care. |
sa.Path[0] = '@' |
} |
|
// Assume path ends at NUL. |
// This is not technically the GNU/Linux semantics for |
// abstract Unix domain sockets--they are supposed |
// to be uninterpreted fixed-size binary blobs--but |
// everyone uses this convention. |
n := 0 |
for n < len(sa.Path) - 3 && sa.Path[n] != 0 { |
n++ |
} |
|
return n, nil |
} |
|
type RawSockaddr struct { |
Family uint16 |
Data [14]int8 |
} |
|
// BindToDevice binds the socket associated with fd to device. |
func BindToDevice(fd int, device string) (err error) { |
return ENOSYS |
} |
|
func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, error) { |
return nil, EAFNOSUPPORT |
} |
/libcall_posix.go
0,0 → 1,384
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// POSIX library calls. |
// This file is compiled as ordinary Go code, |
// but it is also input to mksyscall, |
// which parses the //sys lines and generates library call stubs. |
// Note that sometimes we use a lowercase //sys name and |
// wrap it in our own nicer implementation. |
|
package syscall |
|
import "unsafe" |
|
/* |
* Wrapped |
*/ |
|
//sysnb pipe(p *[2]int) (err error) |
//pipe(p *[2]int) int |
func Pipe(p []int) (err error) { |
if len(p) != 2 { |
return EINVAL |
} |
var pp [2]int |
err = pipe(&pp) |
p[0] = pp[0] |
p[1] = pp[1] |
return |
} |
|
//sys utimes(path string, times *[2]Timeval) (err error) |
//utimes(path *byte, times *[2]Timeval) int |
func Utimes(path string, tv []Timeval) (err error) { |
if len(tv) != 2 { |
return EINVAL |
} |
return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) |
} |
|
//sys getcwd(buf *byte, size Size_t) (err error) |
//getcwd(buf *byte, size Size_t) *byte |
|
const ImplementsGetwd = true |
|
func Getwd() (ret string, err error) { |
for len := Size_t(4096); ; len *= 2 { |
b := make([]byte, len) |
err := getcwd(&b[0], len) |
if err == nil { |
i := 0 |
for b[i] != 0 { |
i++ |
} |
return string(b[0:i]), nil |
} |
if err != ERANGE { |
return "", err |
} |
} |
} |
|
//sysnb getgroups(size int, list *Gid_t) (nn int, err error) |
//getgroups(size int, list *Gid_t) int |
|
func Getgroups() (gids []int, err error) { |
n, err := getgroups(0, nil) |
if err != nil { |
return nil, err |
} |
if n == 0 { |
return nil, nil |
} |
|
// Sanity check group count. Max is 1<<16 on GNU/Linux. |
if n < 0 || n > 1<<20 { |
return nil, EINVAL |
} |
|
a := make([]Gid_t, n) |
n, err = getgroups(n, &a[0]) |
if err != nil { |
return nil, err |
} |
gids = make([]int, n) |
for i, v := range a[0:n] { |
gids[i] = int(v) |
} |
return |
} |
|
//sysnb setgroups(n int, list *Gid_t) (err error) |
//setgroups(n Size_t, list *Gid_t) int |
|
func Setgroups(gids []int) (err error) { |
if len(gids) == 0 { |
return setgroups(0, nil) |
} |
|
a := make([]Gid_t, len(gids)) |
for i, v := range gids { |
a[i] = Gid_t(v) |
} |
return setgroups(len(a), &a[0]) |
} |
|
type WaitStatus uint32 |
|
// The WaitStatus methods are implemented in C, to pick up the macros |
// #defines in <sys/wait.h>. |
|
func (w WaitStatus) Exited() bool |
func (w WaitStatus) Signaled() bool |
func (w WaitStatus) Stopped() bool |
func (w WaitStatus) Continued() bool |
func (w WaitStatus) CoreDump() bool |
func (w WaitStatus) ExitStatus() int |
func (w WaitStatus) Signal() int |
func (w WaitStatus) StopSignal() int |
func (w WaitStatus) TrapCause() int |
|
//sys Mkfifo(path string, mode uint32) (err error) |
//mkfifo(path *byte, mode Mode_t) int |
|
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) |
//select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) int |
|
const nfdbits = unsafe.Sizeof(fds_bits_type) * 8 |
|
type FdSet struct { |
Bits [(FD_SETSIZE + nfdbits - 1) / nfdbits]fds_bits_type |
} |
|
func FDSet(fd int, set *FdSet) { |
set.Bits[fd/nfdbits] |= (1 << (uint)(fd%nfdbits)) |
} |
|
func FDClr(fd int, set *FdSet) { |
set.Bits[fd/nfdbits] &^= (1 << (uint)(fd%nfdbits)) |
} |
|
func FDIsSet(fd int, set *FdSet) bool { |
if set.Bits[fd/nfdbits]&(1<<(uint)(fd%nfdbits)) != 0 { |
return true |
} else { |
return false |
} |
} |
|
func FDZero(set *FdSet) { |
for i := range set.Bits { |
set.Bits[i] = 0 |
} |
} |
|
//sys Access(path string, mode uint32) (err error) |
//access(path *byte, mode int) int |
|
//sys Chdir(path string) (err error) |
//chdir(path *byte) int |
|
//sys Chmod(path string, mode uint32) (err error) |
//chmod(path *byte, mode Mode_t) int |
|
//sys Chown(path string, uid int, gid int) (err error) |
//chown(path *byte, uid Uid_t, gid Gid_t) int |
|
//sys Chroot(path string) (err error) |
//chroot(path *byte) int |
|
//sys Close(fd int) (err error) |
//close(fd int) int |
|
//sys Creat(path string, mode uint32) (fd int, err error) |
//creat(path *byte, mode Mode_t) int |
|
//sysnb Dup(oldfd int) (fd int, err error) |
//dup(oldfd int) int |
|
//sysnb Dup2(oldfd int, newfd int) (err error) |
//dup2(oldfd int, newfd int) int |
|
//sys Exit(code int) |
//exit(code int) |
|
//sys Fchdir(fd int) (err error) |
//fchdir(fd int) int |
|
//sys Fchmod(fd int, mode uint32) (err error) |
//fchmod(fd int, mode Mode_t) int |
|
//sys Fchown(fd int, uid int, gid int) (err error) |
//fchown(fd int, uid Uid_t, gid Gid_t) int |
|
//sys fcntl(fd int, cmd int, arg int) (val int, err error) |
//fcntl(fd int, cmd int, arg int) int |
|
//sys Fdatasync(fd int) (err error) |
//fdatasync(fd int) int |
|
//sys Fsync(fd int) (err error) |
//fsync(fd int) int |
|
//sysnb Getegid() (egid int) |
//getegid() Gid_t |
|
//sysnb Geteuid() (euid int) |
//geteuid() Uid_t |
|
//sysnb Getgid() (gid int) |
//getgid() Gid_t |
|
//sysnb Getpagesize() (pagesize int) |
//getpagesize() int |
|
//sysnb Getpgid(pid int) (pgid int, err error) |
//getpgid(pid Pid_t) Pid_t |
|
//sysnb Getpgrp() (pid int) |
//getpgrp() Pid_t |
|
//sysnb Getpid() (pid int) |
//getpid() Pid_t |
|
//sysnb Getppid() (ppid int) |
//getppid() Pid_t |
|
// FIXME: mksysinfo Rlimit |
// //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) |
// //getrlimit(resource int, rlim *Rlimit) int |
|
//sysnb Getrusage(who int, rusage *Rusage) (err error) |
//getrusage(who int, rusage *Rusage) int |
|
//sysnb gettimeofday(tv *Timeval, tz *byte) (err error) |
//gettimeofday(tv *Timeval, tz *byte) int |
func Gettimeofday(tv *Timeval) (err error) { |
return gettimeofday(tv, nil) |
} |
|
//sysnb Getuid() (uid int) |
//getuid() Uid_t |
|
//sysnb Kill(pid int, sig int) (err error) |
//kill(pid Pid_t, sig int) int |
|
//sys Lchown(path string, uid int, gid int) (err error) |
//lchown(path *byte, uid Uid_t, gid Gid_t) int |
|
//sys Link(oldpath string, newpath string) (err error) |
//link(oldpath *byte, newpath *byte) int |
|
//sys Mkdir(path string, mode uint32) (err error) |
//mkdir(path *byte, mode Mode_t) int |
|
//sys Mknod(path string, mode uint32, dev int) (err error) |
//mknod(path *byte, mode Mode_t, dev _dev_t) int |
|
//sys Mount(source string, target string, fstype string, flags int, data string) (err error) |
//mount(source *byte, target *byte, fstype *byte, flags _C_long, data *byte) int |
|
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error) |
//nanosleep(time *Timespec, leftover *Timespec) int |
|
//sys Pause() (err error) |
//pause() int |
|
//sys Read(fd int, p []byte) (n int, err error) |
//read(fd int, buf *byte, count Size_t) Ssize_t |
|
//sys Readlink(path string, buf []byte) (n int, err error) |
//readlink(path *byte, buf *byte, bufsiz Size_t) Ssize_t |
|
//sys Rename(oldpath string, newpath string) (err error) |
//rename(oldpath *byte, newpath *byte) int |
|
//sys Rmdir(path string) (err error) |
//rmdir(path *byte) int |
|
//sys Setdomainname(p []byte) (err error) |
//setdomainname(name *byte, len Size_t) int |
|
//sys Sethostname(p []byte) (err error) |
//sethostname(name *byte, len Size_t) int |
|
//sysnb Setgid(gid int) (err error) |
//setgid(gid Gid_t) int |
|
//sysnb Setregid(rgid int, egid int) (err error) |
//setregid(rgid Gid_t, egid Gid_t) int |
|
//sysnb Setpgid(pid int, pgid int) (err error) |
//setpgid(pid Pid_t, pgid Pid_t) int |
|
//sysnb Setreuid(ruid int, euid int) (err error) |
//setreuid(ruid Uid_t, euid Uid_t) int |
|
// FIXME: mksysinfo Rlimit |
// //sysnb Setrlimit(resource int, rlim *Rlimit) (err error) |
// //setrlimit(resource int, rlim *Rlimit) int |
|
//sysnb Setsid() (pid int, err error) |
//setsid() Pid_t |
|
//sysnb settimeofday(tv *Timeval, tz *byte) (err error) |
//settimeofday(tv *Timeval, tz *byte) int |
|
func Settimeofday(tv *Timeval) (err error) { |
return settimeofday(tv, nil) |
} |
|
//sysnb Setuid(uid int) (err error) |
//setuid(uid Uid_t) int |
|
//sys Symlink(oldpath string, newpath string) (err error) |
//symlink(oldpath *byte, newpath *byte) int |
|
//sys Sync() |
//sync() |
|
// FIXME: mksysinfo Time_t |
// //sysnb Time(t *Time_t) (tt Time_t, err error) |
// //time(t *Time_t) Time_t |
|
//sysnb Times(tms *Tms) (ticks uintptr, err error) |
//times(tms *Tms) _clock_t |
|
//sysnb Umask(mask int) (oldmask int) |
//umask(mask Mode_t) Mode_t |
|
//sys Unlink(path string) (err error) |
//unlink(path *byte) int |
|
// FIXME: mksysinfo Utimbuf |
// //sys Utime(path string, buf *Utimbuf) (err error) |
// //utime(path *byte, buf *Utimbuf) int |
|
//sys Write(fd int, p []byte) (n int, err error) |
//write(fd int, buf *byte, count Size_t) Ssize_t |
|
//sys munmap(addr uintptr, length uintptr) (err error) |
//munmap(addr *byte, length Size_t) int |
|
//sys Madvise(b []byte, advice int) (err error) |
//madvise(addr *byte, len Size_t, advice int) int |
|
//sys Mprotect(b []byte, prot int) (err error) |
//mprotect(addr *byte, len Size_t, prot int) int |
|
//sys Mlock(b []byte) (err error) |
//mlock(addr *byte, len Size_t) int |
|
//sys Munlock(b []byte) (err error) |
//munlock(addr *byte, len Size_t) int |
|
//sys Mlockall(flags int) (err error) |
//mlockall(flags int) int |
|
//sys Munlockall() (err error) |
//munlockall() int |
|
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } |
|
func NsecToTimespec(nsec int64) (ts Timespec) { |
ts.Sec = Timespec_sec_t(nsec / 1e9) |
ts.Nsec = Timespec_nsec_t(nsec % 1e9) |
return |
} |
|
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 } |
|
func NsecToTimeval(nsec int64) (tv Timeval) { |
nsec += 999 // round up to microsecond |
tv.Sec = Timeval_sec_t(nsec / 1e9) |
tv.Usec = Timeval_usec_t(nsec % 1e9 / 1e3) |
return |
} |
|
//sysnb Tcgetattr(fd int, p *Termios) (err error) |
//tcgetattr(fd int, p *Termios) int |
|
//sys Tcsetattr(fd int, actions int, p *Termios) (err error) |
//tcsetattr(fd int, actions int, p *Termios) int |
/libcall_solaris_sparc.go
0,0 → 1,8
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno) |
//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long |
/libcall_linux_alpha.go
0,0 → 1,13
// Copyright 2012 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// GNU/Linux library calls Alpha specific. |
|
package syscall |
|
//sys Ioperm(from int, num int, on int) (err error) |
//ioperm(from _C_long, num _C_long, on int) int |
|
//sys Iopl(level int) (err error) |
//iopl(level int) int |
/exec_unix.go
0,0 → 1,261
// Copyright 2009 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// +build darwin freebsd linux netbsd openbsd |
|
// Fork, exec, wait, etc. |
|
package syscall |
|
import ( |
"runtime" |
"sync" |
"unsafe" |
) |
|
//sysnb raw_fork() (pid Pid_t, err Errno) |
//fork() Pid_t |
|
//sysnb raw_setsid() (err Errno) |
//setsid() Pid_t |
|
//sysnb raw_setpgid(pid int, pgid int) (err Errno) |
//setpgid(pid Pid_t, pgid Pid_t) int |
|
//sysnb raw_chroot(path *byte) (err Errno) |
//chroot(path *byte) int |
|
//sysnb raw_chdir(path *byte) (err Errno) |
//chdir(path *byte) int |
|
//sysnb raw_fcntl(fd int, cmd int, arg int) (val int, err Errno) |
//fcntl(fd int, cmd int, arg int) int |
|
//sysnb raw_close(fd int) (err Errno) |
//close(fd int) int |
|
//sysnb raw_ioctl(fd int, cmd int, val int) (rval int, err Errno) |
//ioctl(fd int, cmd int, val int) int |
|
//sysnb raw_execve(argv0 *byte, argv **byte, envv **byte) (err Errno) |
//execve(argv0 *byte, argv **byte, envv **byte) int |
|
//sysnb raw_write(fd int, buf *byte, count int) (err Errno) |
//write(fd int, buf *byte, count Size_t) Ssize_t |
|
//sysnb raw_exit(status int) |
//_exit(status int) |
|
//sysnb raw_dup2(oldfd int, newfd int) (err Errno) |
//dup2(oldfd int, newfd int) int |
|
// Note: not raw, returns error rather than Errno. |
//sys read(fd int, p *byte, np int) (n int, err error) |
//read(fd int, buf *byte, count Size_t) Ssize_t |
|
// Lock synchronizing creation of new file descriptors with fork. |
// |
// We want the child in a fork/exec sequence to inherit only the |
// file descriptors we intend. To do that, we mark all file |
// descriptors close-on-exec and then, in the child, explicitly |
// unmark the ones we want the exec'ed program to keep. |
// Unix doesn't make this easy: there is, in general, no way to |
// allocate a new file descriptor close-on-exec. Instead you |
// have to allocate the descriptor and then mark it close-on-exec. |
// If a fork happens between those two events, the child's exec |
// will inherit an unwanted file descriptor. |
// |
// This lock solves that race: the create new fd/mark close-on-exec |
// operation is done holding ForkLock for reading, and the fork itself |
// is done holding ForkLock for writing. At least, that's the idea. |
// There are some complications. |
// |
// Some system calls that create new file descriptors can block |
// for arbitrarily long times: open on a hung NFS server or named |
// pipe, accept on a socket, and so on. We can't reasonably grab |
// the lock across those operations. |
// |
// It is worse to inherit some file descriptors than others. |
// If a non-malicious child accidentally inherits an open ordinary file, |
// that's not a big deal. On the other hand, if a long-lived child |
// accidentally inherits the write end of a pipe, then the reader |
// of that pipe will not see EOF until that child exits, potentially |
// causing the parent program to hang. This is a common problem |
// in threaded C programs that use popen. |
// |
// Luckily, the file descriptors that are most important not to |
// inherit are not the ones that can take an arbitrarily long time |
// to create: pipe returns instantly, and the net package uses |
// non-blocking I/O to accept on a listening socket. |
// The rules for which file descriptor-creating operations use the |
// ForkLock are as follows: |
// |
// 1) Pipe. Does not block. Use the ForkLock. |
// 2) Socket. Does not block. Use the ForkLock. |
// 3) Accept. If using non-blocking mode, use the ForkLock. |
// Otherwise, live with the race. |
// 4) Open. Can block. Use O_CLOEXEC if available (GNU/Linux). |
// Otherwise, live with the race. |
// 5) Dup. Does not block. Use the ForkLock. |
// On GNU/Linux, could use fcntl F_DUPFD_CLOEXEC |
// instead of the ForkLock, but only for dup(fd, -1). |
|
var ForkLock sync.RWMutex |
|
// Convert array of string to array |
// of NUL-terminated byte pointer. |
func StringSlicePtr(ss []string) []*byte { |
bb := make([]*byte, len(ss)+1) |
for i := 0; i < len(ss); i++ { |
bb[i] = StringBytePtr(ss[i]) |
} |
bb[len(ss)] = nil |
return bb |
} |
|
func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) } |
|
func SetNonblock(fd int, nonblocking bool) (err error) { |
flag, err := fcntl(fd, F_GETFL, 0) |
if err != nil { |
return err |
} |
if nonblocking { |
flag |= O_NONBLOCK |
} else { |
flag &= ^O_NONBLOCK |
} |
_, err = fcntl(fd, F_SETFL, flag) |
return err |
} |
|
// Credential holds user and group identities to be assumed |
// by a child process started by StartProcess. |
type Credential struct { |
Uid uint32 // User ID. |
Gid uint32 // Group ID. |
Groups []uint32 // Supplementary group IDs. |
} |
|
// ProcAttr holds attributes that will be applied to a new process started |
// by StartProcess. |
type ProcAttr struct { |
Dir string // Current working directory. |
Env []string // Environment. |
Files []int // File descriptors. |
Sys *SysProcAttr |
} |
|
var zeroProcAttr ProcAttr |
var zeroSysProcAttr SysProcAttr |
|
func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) { |
var p [2]int |
var n int |
var err1 Errno |
var wstatus WaitStatus |
|
if attr == nil { |
attr = &zeroProcAttr |
} |
sys := attr.Sys |
if sys == nil { |
sys = &zeroSysProcAttr |
} |
|
p[0] = -1 |
p[1] = -1 |
|
// Convert args to C form. |
argv0p := StringBytePtr(argv0) |
argvp := StringSlicePtr(argv) |
envvp := StringSlicePtr(attr.Env) |
|
if runtime.GOOS == "freebsd" && len(argv[0]) > len(argv0) { |
argvp[0] = argv0p |
} |
|
var chroot *byte |
if sys.Chroot != "" { |
chroot = StringBytePtr(sys.Chroot) |
} |
var dir *byte |
if attr.Dir != "" { |
dir = StringBytePtr(attr.Dir) |
} |
|
// Acquire the fork lock so that no other threads |
// create new fds that are not yet close-on-exec |
// before we fork. |
ForkLock.Lock() |
|
// Allocate child status pipe close on exec. |
if err = Pipe(p[0:]); err != nil { |
goto error |
} |
if _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != nil { |
goto error |
} |
if _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC); err != nil { |
goto error |
} |
|
// Kick off child. |
pid, err1 = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1]) |
if err1 != 0 { |
goto error |
} |
ForkLock.Unlock() |
|
// Read child error status from pipe. |
Close(p[1]) |
n, err = read(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1))) |
Close(p[0]) |
if err != nil || n != 0 { |
if n == int(unsafe.Sizeof(err1)) { |
err = Errno(err1) |
} |
if err == nil { |
err = EPIPE |
} |
|
// Child failed; wait for it to exit, to make sure |
// the zombies don't accumulate. |
_, err1 := Wait4(pid, &wstatus, 0, nil) |
for err1 == EINTR { |
_, err1 = Wait4(pid, &wstatus, 0, nil) |
} |
return 0, err |
} |
|
// Read got EOF, so pipe closed on exec, so exec succeeded. |
return pid, nil |
|
error: |
if p[0] >= 0 { |
Close(p[0]) |
Close(p[1]) |
} |
ForkLock.Unlock() |
return 0, err |
} |
|
// Combination of fork and exec, careful to be thread safe. |
func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) { |
return forkExec(argv0, argv, attr) |
} |
|
// StartProcess wraps ForkExec for package os. |
func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) { |
pid, err = forkExec(argv0, argv, attr) |
return pid, 0, err |
} |
|
// Ordinary exec. |
func Exec(argv0 string, argv []string, envv []string) (err error) { |
err1 := raw_execve(StringBytePtr(argv0), |
&StringSlicePtr(argv)[0], |
&StringSlicePtr(envv)[0]) |
return Errno(err1) |
} |
/sockcmsg_linux.go
0,0 → 1,38
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// Socket control messages |
|
package syscall |
|
import ( |
"unsafe" |
) |
|
// UnixCredentials encodes credentials into a socket control message |
// for sending to another process. This can be used for |
// authentication. |
func UnixCredentials(ucred *Ucred) []byte { |
buf := make([]byte, CmsgSpace(SizeofUcred)) |
cmsg := (*Cmsghdr)(unsafe.Pointer(&buf[0])) |
cmsg.Level = SOL_SOCKET |
cmsg.Type = SCM_CREDENTIALS |
cmsg.SetLen(CmsgLen(SizeofUcred)) |
*((*Ucred)(cmsgData(cmsg))) = *ucred |
return buf |
} |
|
// ParseUnixCredentials decodes a socket control message that contains |
// credentials in a Ucred structure. To receive such a message, the |
// SO_PASSCRED option must be enabled on the socket. |
func ParseUnixCredentials(msg *SocketControlMessage) (*Ucred, error) { |
if msg.Header.Level != SOL_SOCKET { |
return nil, EINVAL |
} |
if msg.Header.Type != SCM_CREDENTIALS { |
return nil, EINVAL |
} |
ucred := *(*Ucred)(unsafe.Pointer(&msg.Data[0])) |
return &ucred, nil |
} |
/libcall_solaris_amd64.go
0,0 → 1,10
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
// 64-bit ptrace(3C) doesn't exist |
func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno { |
return ENOSYS |
} |
/env_plan9.go
0,0 → 1,128
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// Plan 9 environment variables. |
|
package syscall |
|
import ( |
"errors" |
"sync" |
) |
|
var ( |
// envOnce guards initialization by copyenv, which populates env. |
envOnce sync.Once |
|
// envLock guards env. |
envLock sync.RWMutex |
|
// env maps from an environment variable to its value. |
env map[string]string |
) |
|
func readenv(key string) (string, error) { |
fd, err := Open("/env/"+key, O_RDONLY) |
if err != nil { |
return "", err |
} |
defer Close(fd) |
l, _ := Seek(fd, 0, 2) |
Seek(fd, 0, 0) |
buf := make([]byte, l) |
n, err := Read(fd, buf) |
if err != nil { |
return "", err |
} |
if n > 0 && buf[n-1] == 0 { |
buf = buf[:n-1] |
} |
return string(buf), nil |
} |
|
func writeenv(key, value string) error { |
fd, err := Create("/env/"+key, O_RDWR, 0666) |
if err != nil { |
return err |
} |
defer Close(fd) |
_, err = Write(fd, []byte(value)) |
return err |
} |
|
func copyenv() { |
env = make(map[string]string) |
fd, err := Open("/env", O_RDONLY) |
if err != nil { |
return |
} |
defer Close(fd) |
files, err := readdirnames(fd) |
if err != nil { |
return |
} |
for _, key := range files { |
v, err := readenv(key) |
if err != nil { |
continue |
} |
env[key] = v |
} |
} |
|
func Getenv(key string) (value string, found bool) { |
envOnce.Do(copyenv) |
if len(key) == 0 { |
return "", false |
} |
|
envLock.RLock() |
defer envLock.RUnlock() |
|
v, ok := env[key] |
if !ok { |
return "", false |
} |
return v, true |
} |
|
func Setenv(key, value string) error { |
envOnce.Do(copyenv) |
if len(key) == 0 { |
return errors.New("zero length key") |
} |
|
envLock.Lock() |
defer envLock.Unlock() |
|
err := writeenv(key, value) |
if err != nil { |
return err |
} |
env[key] = value |
return nil |
} |
|
func Clearenv() { |
envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv |
|
envLock.Lock() |
defer envLock.Unlock() |
|
env = make(map[string]string) |
RawSyscall(SYS_RFORK, RFCENVG, 0, 0) |
} |
|
func Environ() []string { |
envOnce.Do(copyenv) |
envLock.RLock() |
defer envLock.RUnlock() |
a := make([]string, len(env)) |
i := 0 |
for k, v := range env { |
a[i] = k + "=" + v |
i++ |
} |
return a |
} |
/route_netbsd.go
0,0 → 1,35
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// Routing sockets and messages for NetBSD |
|
package syscall |
|
import ( |
"unsafe" |
) |
|
func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage { |
switch any.Type { |
case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE: |
p := (*RouteMessage)(unsafe.Pointer(any)) |
rtm := &RouteMessage{} |
rtm.Header = p.Header |
rtm.Data = buf[SizeofRtMsghdr:any.Msglen] |
return rtm |
case RTM_IFINFO: |
p := (*InterfaceMessage)(unsafe.Pointer(any)) |
ifm := &InterfaceMessage{} |
ifm.Header = p.Header |
ifm.Data = buf[SizeofIfMsghdr:any.Msglen] |
return ifm |
case RTM_NEWADDR, RTM_DELADDR: |
p := (*InterfaceAddrMessage)(unsafe.Pointer(any)) |
ifam := &InterfaceAddrMessage{} |
ifam.Header = p.Header |
ifam.Data = buf[SizeofIfaMsghdr:any.Msglen] |
return ifam |
} |
return nil |
} |
/libcall_solaris_386.go
0,0 → 1,12
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
// 32-bit Solaris 2/x86 needs to use _nuname internally, cf. <sys/utsname.h>. |
//sysnb Uname(buf *Utsname) (err error) |
//_nuname(buf *Utsname) int |
|
//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno) |
//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long |
/libcall_support.go
0,0 → 1,12
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// Declarations for functions which are actually written in C. |
|
package syscall |
|
func entersyscall() |
func exitsyscall() |
func GetErrno() Errno |
func SetErrno(Errno) |
/errstr_nor.go
0,0 → 1,33
// errstr.go -- Error strings when there is no strerror_r. |
|
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
import ( |
"sync" |
"unsafe" |
) |
|
//sysnb strerror(errnum int) (buf *byte) |
//strerror(errnum int) *byte |
|
var errstr_lock sync.Mutex |
|
func Errstr(errno int) string { |
errstr_lock.Lock() |
|
bp := strerror(errno) |
b := (*[1000]byte)(unsafe.Pointer(bp)) |
i := 0 |
for b[i] != 0 { |
i++ |
} |
s := string(b[:i]) |
|
errstr_lock.Unlock() |
|
return s |
} |
/env_windows.go
0,0 → 1,77
// Copyright 2010 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// Windows environment variables. |
|
package syscall |
|
import ( |
"unicode/utf16" |
"unsafe" |
) |
|
func Getenv(key string) (value string, found bool) { |
b := make([]uint16, 100) |
n, e := GetEnvironmentVariable(StringToUTF16Ptr(key), &b[0], uint32(len(b))) |
if n == 0 && e == ERROR_ENVVAR_NOT_FOUND { |
return "", false |
} |
if n > uint32(len(b)) { |
b = make([]uint16, n) |
n, e = GetEnvironmentVariable(StringToUTF16Ptr(key), &b[0], uint32(len(b))) |
if n > uint32(len(b)) { |
n = 0 |
} |
} |
if n == 0 { |
return "", false |
} |
return string(utf16.Decode(b[0:n])), true |
} |
|
func Setenv(key, value string) error { |
var v *uint16 |
if len(value) > 0 { |
v = StringToUTF16Ptr(value) |
} |
e := SetEnvironmentVariable(StringToUTF16Ptr(key), v) |
if e != nil { |
return e |
} |
return nil |
} |
|
func Clearenv() { |
for _, s := range Environ() { |
// Environment variables can begin with = |
// so start looking for the separator = at j=1. |
// http://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx |
for j := 1; j < len(s); j++ { |
if s[j] == '=' { |
Setenv(s[0:j], "") |
break |
} |
} |
} |
} |
|
func Environ() []string { |
s, e := GetEnvironmentStrings() |
if e != nil { |
return nil |
} |
defer FreeEnvironmentStrings(s) |
r := make([]string, 0, 50) // Empty with room to grow. |
for from, i, p := 0, 0, (*[1 << 24]uint16)(unsafe.Pointer(s)); true; i++ { |
if p[i] == 0 { |
// empty string marks the end |
if i <= from { |
break |
} |
r = append(r, string(utf16.Decode(p[from:i]))) |
from = i + 1 |
} |
} |
return r |
} |
/exec_stubs.go
0,0 → 1,33
// Copyright 2010 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// Stubs for fork, exec and wait. |
|
package syscall |
|
func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) { |
return -1, ENOSYS |
} |
|
func Exec(argv0 string, argv []string, envv []string) (err int) { |
return ENOSYS |
} |
|
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { |
return -1, ENOSYS |
} |
|
func (w WaitStatus) Exited() bool { return false } |
func (w WaitStatus) Signaled() bool { return false } |
func (w WaitStatus) Stopped() bool { return false } |
func (w WaitStatus) Continued() bool { return false } |
func (w WaitStatus) CoreDump() bool { return false } |
func (w WaitStatus) ExitStatus() int { return 0 } |
func (w WaitStatus) Signal() int { return 0 } |
func (w WaitStatus) StopSignal() int { return 0 } |
func (w WaitStatus) TrapCause() int { return 0 } |
|
func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno { |
return ENOSYS |
} |
/sleep_select.go
0,0 → 1,13
// sleep_select.go -- Sleep using select. |
|
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
func Sleep(nsec int64) (err error) { |
tv := NsecToTimeval(nsec); |
_, err = Select(0, nil, nil, nil, &tv); |
return err; |
} |
/str.go
0,0 → 1,20
// Copyright 2009 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
func itoa(val int) string { // do it here rather than with fmt to avoid dependency |
if val < 0 { |
return "-" + itoa(-val) |
} |
var buf [32]byte // big enough for int64 |
i := len(buf) - 1 |
for val >= 10 { |
buf[i] = byte(val%10 + '0') |
i-- |
val /= 10 |
} |
buf[i] = byte(val + '0') |
return string(buf[i:]) |
} |
/route_openbsd.go
0,0 → 1,35
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// Routing sockets and messages for OpenBSD |
|
package syscall |
|
import ( |
"unsafe" |
) |
|
func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage { |
switch any.Type { |
case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE: |
p := (*RouteMessage)(unsafe.Pointer(any)) |
rtm := &RouteMessage{} |
rtm.Header = p.Header |
rtm.Data = buf[SizeofRtMsghdr:any.Msglen] |
return rtm |
case RTM_IFINFO: |
p := (*InterfaceMessage)(unsafe.Pointer(any)) |
ifm := &InterfaceMessage{} |
ifm.Header = p.Header |
ifm.Data = buf[SizeofIfMsghdr:any.Msglen] |
return ifm |
case RTM_NEWADDR, RTM_DELADDR: |
p := (*InterfaceAddrMessage)(unsafe.Pointer(any)) |
ifam := &InterfaceAddrMessage{} |
ifam.Header = p.Header |
ifam.Data = buf[SizeofIfaMsghdr:any.Msglen] |
return ifam |
} |
return nil |
} |
/libcall_wait4.go
0,0 → 1,20
// Copyright 2009 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// For systems with the wait4 library call. |
|
package syscall |
|
//sys wait4(pid Pid_t, status *int, options int, rusage *Rusage) (wpid Pid_t, err error) |
//wait4(pid Pid_t, status *int, options int, rusage *Rusage) Pid_t |
|
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { |
var status int |
r, err := wait4(Pid_t(pid), &status, options, rusage) |
wpid = int(r) |
if wstatus != nil { |
*wstatus = WaitStatus(status) |
} |
return |
} |
/syscall_unix.go
0,0 → 1,165
// Copyright 2009 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// +build darwin freebsd linux netbsd openbsd |
|
package syscall |
|
import ( |
"runtime" |
"sync" |
"unsafe" |
) |
|
var ( |
Stdin = 0 |
Stdout = 1 |
Stderr = 2 |
) |
|
//extern syscall |
func c_syscall32(trap int32, a1, a2, a3, a4, a5, a6 int32) int32 |
|
//extern syscall |
func c_syscall64(trap int64, a1, a2, a3, a4, a5, a6 int64) int64 |
|
const darwinAMD64 = runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" |
|
// Do a system call. We look at the size of uintptr to see how to pass |
// the arguments, so that we don't pass a 64-bit value when the function |
// expects a 32-bit one. |
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { |
entersyscall() |
var r uintptr |
if unsafe.Sizeof(r) == 4 { |
r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0) |
r = uintptr(r1) |
} else { |
r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0) |
r = uintptr(r1) |
} |
err = GetErrno() |
exitsyscall() |
return r, 0, err |
} |
|
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { |
entersyscall() |
var r uintptr |
if unsafe.Sizeof(r) == 4 { |
r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), |
int32(a4), int32(a5), int32(a6)) |
r = uintptr(r1) |
} else { |
r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), |
int64(a4), int64(a5), int64(a6)) |
r = uintptr(r1) |
} |
err = GetErrno() |
exitsyscall() |
return r, 0, err |
} |
|
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { |
var r uintptr |
if unsafe.Sizeof(r) == 4 { |
r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0) |
r = uintptr(r1) |
} else { |
r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0) |
r = uintptr(r1) |
} |
err = GetErrno() |
return r, 0, err |
} |
|
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { |
var r uintptr |
if unsafe.Sizeof(r) == 4 { |
r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), |
int32(a4), int32(a5), int32(a6)) |
r = uintptr(r1) |
} else { |
r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), |
int64(a4), int64(a5), int64(a6)) |
r = uintptr(r1) |
} |
err = GetErrno() |
return r, 0, err |
} |
|
// Mmap manager, for use by operating system-specific implementations. |
// Gccgo only has one implementation but we do this to correspond to gc. |
|
type mmapper struct { |
sync.Mutex |
active map[*byte][]byte // active mappings; key is last byte in mapping |
mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error) |
munmap func(addr uintptr, length uintptr) error |
} |
|
func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { |
if length <= 0 { |
return nil, EINVAL |
} |
|
// Map the requested memory. |
addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset) |
if errno != nil { |
return nil, errno |
} |
|
// Slice memory layout |
var sl = struct { |
addr uintptr |
len int |
cap int |
}{addr, length, length} |
|
// Use unsafe to turn sl into a []byte. |
b := *(*[]byte)(unsafe.Pointer(&sl)) |
|
// Register mapping in m and return it. |
p := &b[cap(b)-1] |
m.Lock() |
defer m.Unlock() |
m.active[p] = b |
return b, nil |
} |
|
func (m *mmapper) Munmap(data []byte) (err error) { |
if len(data) == 0 || len(data) != cap(data) { |
return EINVAL |
} |
|
// Find the base of the mapping. |
p := &data[cap(data)-1] |
m.Lock() |
defer m.Unlock() |
b := m.active[p] |
if b == nil || &b[0] != &data[0] { |
return EINVAL |
} |
|
// Unmap the memory and update m. |
if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil { |
return errno |
} |
m.active[p] = nil, false |
return nil |
} |
|
var mapper = &mmapper{ |
active: make(map[*byte][]byte), |
mmap: mmap, |
munmap: munmap, |
} |
|
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { |
return mapper.Mmap(fd, offset, length, prot, flags) |
} |
|
func Munmap(b []byte) (err error) { |
return mapper.Munmap(b) |
} |
/libcall_linux.go
0,0 → 1,317
// Copyright 2009 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// GNU/Linux library calls. |
|
package syscall |
|
import "unsafe" |
|
//sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) |
//openat(dirfd int, path *byte, flags int, mode Mode_t) int |
|
//sys futimesat(dirfd int, path *byte, times *[2]Timeval) (err error) |
//futimesat(dirfd int, path *byte, times *[2]Timeval) int |
func Futimesat(dirfd int, path string, tv []Timeval) (err error) { |
if len(tv) != 2 { |
return EINVAL |
} |
return futimesat(dirfd, StringBytePtr(path), (*[2]Timeval)(unsafe.Pointer(&tv[0]))) |
} |
|
func Futimes(fd int, tv []Timeval) (err error) { |
// Believe it or not, this is the best we can do on GNU/Linux |
// (and is what glibc does). |
return Utimes("/proc/self/fd/"+itoa(fd), tv) |
} |
|
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) |
//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long |
|
//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno) |
//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long |
|
func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, err error) { |
// The peek requests are machine-size oriented, so we wrap it |
// to retrieve arbitrary-length data. |
|
// The ptrace syscall differs from glibc's ptrace. |
// Peeks returns the word in *data, not as the return value. |
|
var buf [sizeofPtr]byte |
|
// Leading edge. PEEKTEXT/PEEKDATA don't require aligned |
// access (PEEKUSER warns that it might), but if we don't |
// align our reads, we might straddle an unmapped page |
// boundary and not get the bytes leading up to the page |
// boundary. |
n := 0 |
if addr%sizeofPtr != 0 { |
err = ptrace(req, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0]))) |
if err != nil { |
return 0, err |
} |
n += copy(out, buf[addr%sizeofPtr:]) |
out = out[n:] |
} |
|
// Remainder. |
for len(out) > 0 { |
// We use an internal buffer to gaurantee alignment. |
// It's not documented if this is necessary, but we're paranoid. |
err = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0]))) |
if err != nil { |
return n, err |
} |
copied := copy(out, buf[0:]) |
n += copied |
out = out[copied:] |
} |
|
return n, nil |
} |
|
func PtracePeekText(pid int, addr uintptr, out []byte) (count int, err error) { |
return ptracePeek(PTRACE_PEEKTEXT, pid, addr, out) |
} |
|
func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) { |
return ptracePeek(PTRACE_PEEKDATA, pid, addr, out) |
} |
|
func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, err error) { |
// As for ptracePeek, we need to align our accesses to deal |
// with the possibility of straddling an invalid page. |
|
// Leading edge. |
n := 0 |
if addr%sizeofPtr != 0 { |
var buf [sizeofPtr]byte |
err = ptrace(peekReq, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0]))) |
if err != nil { |
return 0, err |
} |
n += copy(buf[addr%sizeofPtr:], data) |
word := *((*uintptr)(unsafe.Pointer(&buf[0]))) |
err = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word) |
if err != nil { |
return 0, err |
} |
data = data[n:] |
} |
|
// Interior. |
for len(data) > int(sizeofPtr) { |
word := *((*uintptr)(unsafe.Pointer(&data[0]))) |
err = ptrace(pokeReq, pid, addr+uintptr(n), word) |
if err != nil { |
return n, err |
} |
n += int(sizeofPtr) |
data = data[sizeofPtr:] |
} |
|
// Trailing edge. |
if len(data) > 0 { |
var buf [sizeofPtr]byte |
err = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0]))) |
if err != nil { |
return n, err |
} |
copy(buf[0:], data) |
word := *((*uintptr)(unsafe.Pointer(&buf[0]))) |
err = ptrace(pokeReq, pid, addr+uintptr(n), word) |
if err != nil { |
return n, err |
} |
n += len(data) |
} |
|
return n, nil |
} |
|
func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) { |
return ptracePoke(PTRACE_POKETEXT, PTRACE_PEEKTEXT, pid, addr, data) |
} |
|
func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) { |
return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data) |
} |
|
func PtraceSetOptions(pid int, options int) (err error) { |
return ptrace(PTRACE_SETOPTIONS, pid, 0, uintptr(options)) |
} |
|
func PtraceGetEventMsg(pid int) (msg uint, err error) { |
var data _C_long |
err = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data))) |
msg = uint(data) |
return |
} |
|
func PtraceCont(pid int, signal int) (err error) { |
return ptrace(PTRACE_CONT, pid, 0, uintptr(signal)) |
} |
|
func PtraceSingleStep(pid int) (err error) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) } |
|
func PtraceAttach(pid int) (err error) { return ptrace(PTRACE_ATTACH, pid, 0, 0) } |
|
func PtraceDetach(pid int) (err error) { return ptrace(PTRACE_DETACH, pid, 0, 0) } |
|
// FIXME: mksysinfo needs to produce LINUX_REBOOT_MAGIC[12]. |
|
// //sys reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) |
// //reboot(magic1 uint, magic2 uint, cmd int, arg *byte) int |
// func Reboot(cmd int) (err error) { |
// return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "") |
// } |
|
//sys Acct(path string) (err error) |
//acct(path *byte) int |
|
// FIXME: mksysinfo Timex |
// //sys Adjtimex(buf *Timex) (state int, err error) |
// //adjtimex(buf *Timex) int |
|
//sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error) |
//faccessat(dirfd int, pathname *byte, mode int, flags int) int |
|
//sys Fallocate(fd int, mode uint32, off int64, len int64) (err error) |
//fallocate(fd int, mode int, offset Offset_t, len Offset_t) int |
|
//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) |
//fchmodat(dirfd int, pathname *byte, mode Mode_t, flags int) int |
|
//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) |
//fchownat(dirfd int, path *byte, owner Uid_t, group Gid_t, flags int) int |
|
//sys Flock(fd int, how int) (err error) |
//flock(fd int, how int) int |
|
//sys Fstatfs(fd int, buf *Statfs_t) (err error) |
//fstatfs(fd int, buf *Statfs_t) int |
|
func Gettid() (tid int) { |
r1, _, _ := Syscall(SYS_GETTID, 0, 0, 0) |
return int(r1) |
} |
|
// FIXME: mksysinfo linux_dirent |
// Or just abandon this function. |
// //sys Getdents(fd int, buf []byte) (n int, err error) |
// //getdents64(fd int, buf *byte, count uint) |
|
//sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) |
//inotify_add_watch(fd int, pathname *byte, mask uint32) int |
|
//sysnb InotifyInit() (fd int, err error) |
//inotify_init() int |
|
// FIXME: Only in glibc 2.9 and later. |
// //sysnb InotifyInit1(flags int) (fd int, err error) |
// //inotify_init1(flags int) int |
|
//sysnb InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) |
//inotify_rm_watch(fd int, wd uint32) int |
|
//sys Klogctl(typ int, buf []byte) (n int, err error) |
//klogctl(typ int, bufp *byte, len int) int |
|
//sys Mkdirat(dirfd int, path string, mode uint32) (err error) |
//mkdirat(dirfd int, path *byte, mode Mode_t) int |
|
//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) |
//mknodat(dirfd int, path *byte, mode Mode_t, dev _dev_t) int |
|
//sys PivotRoot(newroot string, putold string) (err error) |
//pivot_root(newroot *byte, putold *byte) int |
|
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) |
//renameat(olddirfd int, oldpath *byte, newdirfd int, newpath *byte) int |
|
//sys sendfile(outfd int, infd int, offset *Offset_t, count int) (written int, err error) |
//sendfile64(outfd int, infd int, offset *Offset_t, count Size_t) Ssize_t |
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { |
var soff Offset_t |
var psoff *Offset_t |
if offset != nil { |
psoff = &soff |
} |
written, err = sendfile(outfd, infd, psoff, count) |
if offset != nil { |
*offset = int64(soff) |
} |
return |
} |
|
//sys Setfsgid(gid int) (err error) |
//setfsgid(gid Gid_t) int |
|
//sys Setfsuid(uid int) (err error) |
//setfsuid(uid Uid_t) int |
|
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) |
//setresgid(rgid Gid_t, egid Gid_t, sgid Gid_t) int |
|
//sysnb Setresuid(ruid int, eguid int, suid int) (err error) |
//setresuid(ruid Uid_t, euid Uid_t, suid Uid_t) int |
|
//sys splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len int, flags int) (n int64, err error) |
//splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len Size_t, flags uint) Ssize_t |
func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) { |
var lroff _loff_t |
var plroff *_loff_t |
if roff != nil { |
plroff = &lroff |
} |
var lwoff _loff_t |
var plwoff *_loff_t |
if woff != nil { |
plwoff = &lwoff |
} |
n, err = splice(rfd, plroff, wfd, plwoff, len, flags) |
if roff != nil { |
*roff = int64(lroff) |
} |
if woff != nil { |
*woff = int64(lwoff) |
} |
return |
} |
|
//sys Statfs(path string, buf *Statfs_t) (err error) |
//statfs(path *byte, buf *Statfs_t) int |
|
// FIXME: Only in glibc 2.6 and later. |
// //sys SyncFileRange(fd int, off int64, n int64, flags int) (err error) |
// //sync_file_range(fd int, off Offset_t, n Offset_t, flags uint) int |
|
// FIXME: mksysinfo Sysinfo_t |
// //sysnb Sysinfo(info *Sysinfo_t) (err error) |
// //sysinfo(info *Sysinfo_t) int |
|
//sys Tee(rfd int, wfd int, len int, flags int) (n int64, err error) |
//tee(rfd int, wfd int, len Size_t, flags uint) Ssize_t |
|
// FIXME: Only available as a syscall. |
// //sysnb Tgkill(tgid int, tid int, sig int) (err error) |
// //tgkill(tgid int, tid int, sig int) int |
|
//sys unlinkat(dirfd int, path string, flags int) (err error) |
//unlinkat(dirfd int, path *byte, flags int) int |
|
func Unlinkat(dirfd int, path string) (err error) { |
return unlinkat(dirfd, path, 0) |
} |
|
//sys Unmount(target string, flags int) (err error) = SYS_UMOUNT2 |
//umount2(target *byte, flags int) int |
|
//sys Unshare(flags int) (err error) |
//unshare(flags int) int |
|
// FIXME: mksysinfo Ustat_t |
// //sys Ustat(dev int, ubuf *Ustat_t) (err error) |
// //ustat(dev _dev_t, ubuf *Ustat_t) int |
/libcall_posix_regfile.go
0,0 → 1,38
// Copyright 2009 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// POSIX library calls on systems which do not use the largefile |
// interface. |
|
package syscall |
|
//sys Fstat(fd int, stat *Stat_t) (err error) |
//fstat(fd int, stat *Stat_t) int |
|
//sys Ftruncate(fd int, length int64) (err error) |
//ftruncate(fd int, length Offset_t) int |
|
//sys Lstat(path string, stat *Stat_t) (err error) |
//lstat(path *byte, stat *Stat_t) int |
|
//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) |
//mmap(addr *byte, length Size_t, prot int, flags int, fd int, offset Offset_t) *byte |
|
//sys Open(path string, mode int, perm uint32) (fd int, err error) |
//open(path *byte, mode int, perm Mode_t) int |
|
//sys Pread(fd int, p []byte, offset int64) (n int, err error) |
//pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t |
|
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) |
//pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t |
|
//sys Seek(fd int, offset int64, whence int) (off int64, err error) |
//lseek(fd int, offset Offset_t, whence int) Offset_t |
|
//sys Stat(path string, stat *Stat_t) (err error) |
//stat(path *byte, stat *Stat_t) int |
|
//sys Truncate(path string, length int64) (err error) |
//truncate(path *byte, length Offset_t) int |
/security_windows.go
0,0 → 1,359
// Copyright 2012 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
import ( |
"unsafe" |
) |
|
const ( |
STANDARD_RIGHTS_REQUIRED = 0xf0000 |
STANDARD_RIGHTS_READ = 0x20000 |
STANDARD_RIGHTS_WRITE = 0x20000 |
STANDARD_RIGHTS_EXECUTE = 0x20000 |
STANDARD_RIGHTS_ALL = 0x1F0000 |
) |
|
const ( |
NameUnknown = 0 |
NameFullyQualifiedDN = 1 |
NameSamCompatible = 2 |
NameDisplay = 3 |
NameUniqueId = 6 |
NameCanonical = 7 |
NameUserPrincipal = 8 |
NameCanonicalEx = 9 |
NameServicePrincipal = 10 |
NameDnsDomain = 12 |
) |
|
// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL. |
// http://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx |
//sys TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW |
//sys GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW |
|
// TranslateAccountName converts a directory service |
// object name from one format to another. |
func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) { |
u := StringToUTF16Ptr(username) |
b := make([]uint16, 50) |
n := uint32(len(b)) |
e := TranslateName(u, from, to, &b[0], &n) |
if e != nil { |
if e != ERROR_INSUFFICIENT_BUFFER { |
return "", e |
} |
// make receive buffers of requested size and try again |
b = make([]uint16, n) |
e = TranslateName(u, from, to, &b[0], &n) |
if e != nil { |
return "", e |
} |
} |
return UTF16ToString(b), nil |
} |
|
type UserInfo10 struct { |
Name *uint16 |
Comment *uint16 |
UsrComment *uint16 |
FullName *uint16 |
} |
|
//sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo |
//sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree |
|
const ( |
// do not reorder |
SidTypeUser = 1 << iota |
SidTypeGroup |
SidTypeDomain |
SidTypeAlias |
SidTypeWellKnownGroup |
SidTypeDeletedAccount |
SidTypeInvalid |
SidTypeUnknown |
SidTypeComputer |
SidTypeLabel |
) |
|
//sys LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW |
//sys LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW |
//sys ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW |
//sys ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW |
//sys GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid |
//sys CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid |
|
// The security identifier (SID) structure is a variable-length |
// structure used to uniquely identify users or groups. |
type SID struct{} |
|
// StringToSid converts a string-format security identifier |
// sid into a valid, functional sid. |
func StringToSid(s string) (*SID, error) { |
var sid *SID |
e := ConvertStringSidToSid(StringToUTF16Ptr(s), &sid) |
if e != nil { |
return nil, e |
} |
defer LocalFree((Handle)(unsafe.Pointer(sid))) |
return sid.Copy() |
} |
|
// LookupSID retrieves a security identifier sid for the account |
// and the name of the domain on which the account was found. |
// System specify target computer to search. |
func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) { |
if len(account) == 0 { |
return nil, "", 0, EINVAL |
} |
acc := StringToUTF16Ptr(account) |
var sys *uint16 |
if len(system) > 0 { |
sys = StringToUTF16Ptr(system) |
} |
db := make([]uint16, 50) |
dn := uint32(len(db)) |
b := make([]byte, 50) |
n := uint32(len(b)) |
sid = (*SID)(unsafe.Pointer(&b[0])) |
e := LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType) |
if e != nil { |
if e != ERROR_INSUFFICIENT_BUFFER { |
return nil, "", 0, e |
} |
// make receive buffers of requested size and try again |
b = make([]byte, n) |
sid = (*SID)(unsafe.Pointer(&b[0])) |
db = make([]uint16, dn) |
e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType) |
if e != nil { |
return nil, "", 0, e |
} |
} |
return sid, UTF16ToString(db), accType, nil |
} |
|
// String converts sid to a string format |
// suitable for display, storage, or transmission. |
func (sid *SID) String() (string, error) { |
var s *uint16 |
e := ConvertSidToStringSid(sid, &s) |
if e != nil { |
return "", e |
} |
defer LocalFree((Handle)(unsafe.Pointer(s))) |
return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil |
} |
|
// Len returns the length, in bytes, of a valid security identifier sid. |
func (sid *SID) Len() int { |
return int(GetLengthSid(sid)) |
} |
|
// Copy creates a duplicate of security identifier sid. |
func (sid *SID) Copy() (*SID, error) { |
b := make([]byte, sid.Len()) |
sid2 := (*SID)(unsafe.Pointer(&b[0])) |
e := CopySid(uint32(len(b)), sid2, sid) |
if e != nil { |
return nil, e |
} |
return sid2, nil |
} |
|
// LookupAccount retrieves the name of the account for this sid |
// and the name of the first domain on which this sid is found. |
// System specify target computer to search for. |
func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) { |
var sys *uint16 |
if len(system) > 0 { |
sys = StringToUTF16Ptr(system) |
} |
b := make([]uint16, 50) |
n := uint32(len(b)) |
db := make([]uint16, 50) |
dn := uint32(len(db)) |
e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType) |
if e != nil { |
if e != ERROR_INSUFFICIENT_BUFFER { |
return "", "", 0, e |
} |
// make receive buffers of requested size and try again |
b = make([]uint16, n) |
db = make([]uint16, dn) |
e = LookupAccountSid(nil, sid, &b[0], &n, &db[0], &dn, &accType) |
if e != nil { |
return "", "", 0, e |
} |
} |
return UTF16ToString(b), UTF16ToString(db), accType, nil |
} |
|
const ( |
// do not reorder |
TOKEN_ASSIGN_PRIMARY = 1 << iota |
TOKEN_DUPLICATE |
TOKEN_IMPERSONATE |
TOKEN_QUERY |
TOKEN_QUERY_SOURCE |
TOKEN_ADJUST_PRIVILEGES |
TOKEN_ADJUST_GROUPS |
TOKEN_ADJUST_DEFAULT |
|
TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | |
TOKEN_ASSIGN_PRIMARY | |
TOKEN_DUPLICATE | |
TOKEN_IMPERSONATE | |
TOKEN_QUERY | |
TOKEN_QUERY_SOURCE | |
TOKEN_ADJUST_PRIVILEGES | |
TOKEN_ADJUST_GROUPS | |
TOKEN_ADJUST_DEFAULT |
TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY |
TOKEN_WRITE = STANDARD_RIGHTS_WRITE | |
TOKEN_ADJUST_PRIVILEGES | |
TOKEN_ADJUST_GROUPS | |
TOKEN_ADJUST_DEFAULT |
TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE |
) |
|
const ( |
// do not reorder |
TokenUser = 1 + iota |
TokenGroups |
TokenPrivileges |
TokenOwner |
TokenPrimaryGroup |
TokenDefaultDacl |
TokenSource |
TokenType |
TokenImpersonationLevel |
TokenStatistics |
TokenRestrictedSids |
TokenSessionId |
TokenGroupsAndPrivileges |
TokenSessionReference |
TokenSandBoxInert |
TokenAuditPolicy |
TokenOrigin |
TokenElevationType |
TokenLinkedToken |
TokenElevation |
TokenHasRestrictions |
TokenAccessInformation |
TokenVirtualizationAllowed |
TokenVirtualizationEnabled |
TokenIntegrityLevel |
TokenUIAccess |
TokenMandatoryPolicy |
TokenLogonSid |
MaxTokenInfoClass |
) |
|
type SIDAndAttributes struct { |
Sid *SID |
Attributes uint32 |
} |
|
type Tokenuser struct { |
User SIDAndAttributes |
} |
|
type Tokenprimarygroup struct { |
PrimaryGroup *SID |
} |
|
//sys OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken |
//sys GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation |
//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW |
|
// An access token contains the security information for a logon session. |
// The system creates an access token when a user logs on, and every |
// process executed on behalf of the user has a copy of the token. |
// The token identifies the user, the user's groups, and the user's |
// privileges. The system uses the token to control access to securable |
// objects and to control the ability of the user to perform various |
// system-related operations on the local computer. |
type Token Handle |
|
// OpenCurrentProcessToken opens the access token |
// associated with current process. |
func OpenCurrentProcessToken() (Token, error) { |
p, e := GetCurrentProcess() |
if e != nil { |
return 0, e |
} |
var t Token |
e = OpenProcessToken(p, TOKEN_QUERY, &t) |
if e != nil { |
return 0, e |
} |
return t, nil |
} |
|
// Close releases access to access token. |
func (t Token) Close() error { |
return CloseHandle(Handle(t)) |
} |
|
// getInfo retrieves a specified type of information about an access token. |
func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) { |
b := make([]byte, initSize) |
var n uint32 |
e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n) |
if e != nil { |
if e != ERROR_INSUFFICIENT_BUFFER { |
return nil, e |
} |
// make receive buffers of requested size and try again |
b = make([]byte, n) |
e = GetTokenInformation(t, class, &b[0], uint32(len(b)), &n) |
if e != nil { |
return nil, e |
} |
} |
return unsafe.Pointer(&b[0]), nil |
} |
|
// GetTokenUser retrieves access token t user account information. |
func (t Token) GetTokenUser() (*Tokenuser, error) { |
i, e := t.getInfo(TokenUser, 50) |
if e != nil { |
return nil, e |
} |
return (*Tokenuser)(i), nil |
} |
|
// GetTokenPrimaryGroup retrieves access token t primary group information. |
// A pointer to a SID structure representing a group that will become |
// the primary group of any objects created by a process using this access token. |
func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) { |
i, e := t.getInfo(TokenPrimaryGroup, 50) |
if e != nil { |
return nil, e |
} |
return (*Tokenprimarygroup)(i), nil |
} |
|
// GetUserProfileDirectory retrieves path to the |
// root directory of the access token t user's profile. |
func (t Token) GetUserProfileDirectory() (string, error) { |
b := make([]uint16, 100) |
n := uint32(len(b)) |
e := GetUserProfileDirectory(t, &b[0], &n) |
if e != nil { |
if e != ERROR_INSUFFICIENT_BUFFER { |
return "", e |
} |
// make receive buffers of requested size and try again |
b = make([]uint16, n) |
e = GetUserProfileDirectory(t, &b[0], &n) |
if e != nil { |
return "", e |
} |
} |
return UTF16ToString(b), nil |
} |
/errstr.go
0,0 → 1,27
// errstr.go -- Error strings. |
|
// Copyright 2009 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
//sysnb strerror_r(errnum int, buf []byte) (err error) |
//strerror_r(errnum int, buf *byte, buflen Size_t) int |
|
func Errstr(errnum int) string { |
for len := 128; ; len *= 2 { |
b := make([]byte, len) |
err := strerror_r(errnum, b) |
if err == nil { |
i := 0 |
for b[i] != 0 { |
i++ |
} |
return string(b[:i]) |
} |
if err != ERANGE { |
return "Errstr failure" |
} |
} |
} |
/libcall_waitpid.go
0,0 → 1,20
// Copyright 2009 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// For systems with the waitpid library call. |
|
package syscall |
|
//sys waitpid(pid Pid_t, status *int, options int) (wpid Pid_t, err error) |
//waitpid(pid Pid_t, status *int, options int) Pid_t |
|
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { |
var status int |
r, err := waitpid(Pid_t(pid), &status, options) |
wpid = int(r) |
if wstatus != nil { |
*wstatus = WaitStatus(status) |
} |
return |
} |
/netlink_linux.go
0,0 → 1,226
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// Netlink sockets and messages |
|
package syscall |
|
import ( |
"unsafe" |
) |
|
// Round the length of a netlink message up to align it properly. |
func nlmAlignOf(msglen int) int { |
return (msglen + NLMSG_ALIGNTO - 1) & ^(NLMSG_ALIGNTO - 1) |
} |
|
// Round the length of a netlink route attribute up to align it |
// properly. |
func rtaAlignOf(attrlen int) int { |
return (attrlen + RTA_ALIGNTO - 1) & ^(RTA_ALIGNTO - 1) |
} |
|
// NetlinkRouteRequest represents the request message to receive |
// routing and link states from the kernel. |
type NetlinkRouteRequest struct { |
Header NlMsghdr |
Data RtGenmsg |
} |
|
func (rr *NetlinkRouteRequest) toWireFormat() []byte { |
b := make([]byte, rr.Header.Len) |
b[0] = byte(rr.Header.Len) |
b[1] = byte(rr.Header.Len >> 8) |
b[2] = byte(rr.Header.Len >> 16) |
b[3] = byte(rr.Header.Len >> 24) |
b[4] = byte(rr.Header.Type) |
b[5] = byte(rr.Header.Type >> 8) |
b[6] = byte(rr.Header.Flags) |
b[7] = byte(rr.Header.Flags >> 8) |
b[8] = byte(rr.Header.Seq) |
b[9] = byte(rr.Header.Seq >> 8) |
b[10] = byte(rr.Header.Seq >> 16) |
b[11] = byte(rr.Header.Seq >> 24) |
b[12] = byte(rr.Header.Pid) |
b[13] = byte(rr.Header.Pid >> 8) |
b[14] = byte(rr.Header.Pid >> 16) |
b[15] = byte(rr.Header.Pid >> 24) |
b[16] = byte(rr.Data.Family) |
return b |
} |
|
func newNetlinkRouteRequest(proto, seq, family int) []byte { |
rr := &NetlinkRouteRequest{} |
rr.Header.Len = uint32(NLMSG_HDRLEN + SizeofRtGenmsg) |
rr.Header.Type = uint16(proto) |
rr.Header.Flags = NLM_F_DUMP | NLM_F_REQUEST |
rr.Header.Seq = uint32(seq) |
rr.Data.Family = uint8(family) |
return rr.toWireFormat() |
} |
|
// NetlinkRIB returns routing information base, as known as RIB, |
// which consists of network facility information, states and |
// parameters. |
func NetlinkRIB(proto, family int) ([]byte, error) { |
var ( |
lsanl SockaddrNetlink |
tab []byte |
) |
|
s, e := Socket(AF_NETLINK, SOCK_RAW, 0) |
if e != nil { |
return nil, e |
} |
defer Close(s) |
|
lsanl.Family = AF_NETLINK |
e = Bind(s, &lsanl) |
if e != nil { |
return nil, e |
} |
|
seq := 1 |
wb := newNetlinkRouteRequest(proto, seq, family) |
e = Sendto(s, wb, 0, &lsanl) |
if e != nil { |
return nil, e |
} |
|
for { |
var ( |
rb []byte |
nr int |
lsa Sockaddr |
) |
|
rb = make([]byte, Getpagesize()) |
nr, _, e = Recvfrom(s, rb, 0) |
if e != nil { |
return nil, e |
} |
if nr < NLMSG_HDRLEN { |
return nil, EINVAL |
} |
rb = rb[:nr] |
tab = append(tab, rb...) |
|
msgs, _ := ParseNetlinkMessage(rb) |
for _, m := range msgs { |
if lsa, e = Getsockname(s); e != nil { |
return nil, e |
} |
switch v := lsa.(type) { |
case *SockaddrNetlink: |
if m.Header.Seq != uint32(seq) || m.Header.Pid != v.Pid { |
return nil, EINVAL |
} |
default: |
return nil, EINVAL |
} |
if m.Header.Type == NLMSG_DONE { |
goto done |
} |
if m.Header.Type == NLMSG_ERROR { |
return nil, EINVAL |
} |
} |
} |
|
done: |
return tab, nil |
} |
|
// NetlinkMessage represents the netlink message. |
type NetlinkMessage struct { |
Header NlMsghdr |
Data []byte |
} |
|
// ParseNetlinkMessage parses buf as netlink messages and returns |
// the slice containing the NetlinkMessage structs. |
func ParseNetlinkMessage(buf []byte) ([]NetlinkMessage, error) { |
var ( |
h *NlMsghdr |
dbuf []byte |
dlen int |
e error |
msgs []NetlinkMessage |
) |
|
for len(buf) >= NLMSG_HDRLEN { |
h, dbuf, dlen, e = netlinkMessageHeaderAndData(buf) |
if e != nil { |
break |
} |
m := NetlinkMessage{} |
m.Header = *h |
m.Data = dbuf[:int(h.Len)-NLMSG_HDRLEN] |
msgs = append(msgs, m) |
buf = buf[dlen:] |
} |
|
return msgs, e |
} |
|
func netlinkMessageHeaderAndData(buf []byte) (*NlMsghdr, []byte, int, error) { |
h := (*NlMsghdr)(unsafe.Pointer(&buf[0])) |
if int(h.Len) < NLMSG_HDRLEN || int(h.Len) > len(buf) { |
return nil, nil, 0, EINVAL |
} |
return h, buf[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), nil |
} |
|
// NetlinkRouteAttr represents the netlink route attribute. |
type NetlinkRouteAttr struct { |
Attr RtAttr |
Value []byte |
} |
|
// ParseNetlinkRouteAttr parses msg's payload as netlink route |
// attributes and returns the slice containing the NetlinkRouteAttr |
// structs. |
func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, error) { |
var ( |
buf []byte |
a *RtAttr |
alen int |
vbuf []byte |
e error |
attrs []NetlinkRouteAttr |
) |
|
switch msg.Header.Type { |
case RTM_NEWLINK, RTM_DELLINK: |
buf = msg.Data[SizeofIfInfomsg:] |
case RTM_NEWADDR, RTM_DELADDR: |
buf = msg.Data[SizeofIfAddrmsg:] |
case RTM_NEWROUTE, RTM_DELROUTE: |
buf = msg.Data[SizeofRtMsg:] |
default: |
return nil, EINVAL |
} |
|
for len(buf) >= SizeofRtAttr { |
a, vbuf, alen, e = netlinkRouteAttrAndValue(buf) |
if e != nil { |
break |
} |
ra := NetlinkRouteAttr{} |
ra.Attr = *a |
ra.Value = vbuf[:int(a.Len)-SizeofRtAttr] |
attrs = append(attrs, ra) |
buf = buf[alen:] |
} |
|
return attrs, nil |
} |
|
func netlinkRouteAttrAndValue(buf []byte) (*RtAttr, []byte, int, error) { |
h := (*RtAttr)(unsafe.Pointer(&buf[0])) |
if int(h.Len) < SizeofRtAttr || int(h.Len) > len(buf) { |
return nil, nil, 0, EINVAL |
} |
return h, buf[SizeofRtAttr:], rtaAlignOf(int(h.Len)), nil |
} |
/syscall_linux_amd64.go
0,0 → 1,25
// syscall_linux_amd64.go -- GNU/Linux 386 specific support |
|
// Copyright 2009 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
import "unsafe" |
|
func (r *PtraceRegs) PC() uint64 { |
return r.Rip |
} |
|
func (r *PtraceRegs) SetPC(pc uint64) { |
r.Rip = pc |
} |
|
func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) { |
return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout))) |
} |
|
func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) { |
return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) |
} |
/route_bsd.go
0,0 → 1,201
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// +build darwin freebsd netbsd openbsd |
|
// Routing sockets and messages |
|
package syscall |
|
import ( |
"unsafe" |
) |
|
// Round the length of a raw sockaddr up to align it properly. |
func rsaAlignOf(salen int) int { |
salign := sizeofPtr |
// NOTE: It seems like 64-bit Darwin kernel still requires 32-bit |
// aligned access to BSD subsystem. |
if darwinAMD64 { |
salign = 4 |
} |
if salen == 0 { |
return salign |
} |
return (salen + salign - 1) & ^(salign - 1) |
} |
|
// RouteRIB returns routing information base, as known as RIB, |
// which consists of network facility information, states and |
// parameters. |
func RouteRIB(facility, param int) ([]byte, error) { |
mib := []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(facility), _C_int(param)} |
|
// Find size. |
n := uintptr(0) |
if err := sysctl(mib, nil, &n, nil, 0); err != nil { |
return nil, err |
} |
if n == 0 { |
return nil, nil |
} |
|
tab := make([]byte, n) |
if err := sysctl(mib, &tab[0], &n, nil, 0); err != nil { |
return nil, err |
} |
|
return tab[:n], nil |
} |
|
// RoutingMessage represents a routing message. |
type RoutingMessage interface { |
sockaddr() []Sockaddr |
} |
|
const anyMessageLen = int(unsafe.Sizeof(anyMessage{})) |
|
type anyMessage struct { |
Msglen uint16 |
Version uint8 |
Type uint8 |
} |
|
// RouteMessage represents a routing message containing routing |
// entries. |
type RouteMessage struct { |
Header RtMsghdr |
Data []byte |
} |
|
const rtaRtMask = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_GENMASK |
|
func (m *RouteMessage) sockaddr() []Sockaddr { |
var ( |
af int |
sas [4]Sockaddr |
) |
|
buf := m.Data[:] |
for i := uint(0); i < RTAX_MAX; i++ { |
if m.Header.Addrs&rtaRtMask&(1<<i) == 0 { |
continue |
} |
rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0])) |
switch i { |
case RTAX_DST, RTAX_GATEWAY: |
sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa))) |
if err != nil { |
return nil |
} |
if i == RTAX_DST { |
af = int(rsa.Family) |
} |
sas[i] = sa |
case RTAX_NETMASK, RTAX_GENMASK: |
switch af { |
case AF_INET: |
rsa4 := (*RawSockaddrInet4)(unsafe.Pointer(&buf[0])) |
sa := new(SockaddrInet4) |
for j := 0; rsa4.Len > 0 && j < int(rsa4.Len)-int(unsafe.Offsetof(rsa4.Addr)); j++ { |
sa.Addr[j] = rsa4.Addr[j] |
} |
sas[i] = sa |
case AF_INET6: |
rsa6 := (*RawSockaddrInet6)(unsafe.Pointer(&buf[0])) |
sa := new(SockaddrInet6) |
for j := 0; rsa6.Len > 0 && j < int(rsa6.Len)-int(unsafe.Offsetof(rsa6.Addr)); j++ { |
sa.Addr[j] = rsa6.Addr[j] |
} |
sas[i] = sa |
} |
} |
buf = buf[rsaAlignOf(int(rsa.Len)):] |
} |
|
return sas[:] |
} |
|
// InterfaceMessage represents a routing message containing |
// network interface entries. |
type InterfaceMessage struct { |
Header IfMsghdr |
Data []byte |
} |
|
func (m *InterfaceMessage) sockaddr() (sas []Sockaddr) { |
if m.Header.Addrs&RTA_IFP == 0 { |
return nil |
} |
sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(&m.Data[0]))) |
if err != nil { |
return nil |
} |
return append(sas, sa) |
} |
|
// InterfaceAddrMessage represents a routing message containing |
// network interface address entries. |
type InterfaceAddrMessage struct { |
Header IfaMsghdr |
Data []byte |
} |
|
const rtaIfaMask = RTA_IFA | RTA_NETMASK | RTA_BRD |
|
func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) { |
if m.Header.Addrs&rtaIfaMask == 0 { |
return nil |
} |
|
buf := m.Data[:] |
for i := uint(0); i < RTAX_MAX; i++ { |
if m.Header.Addrs&rtaIfaMask&(1<<i) == 0 { |
continue |
} |
rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0])) |
switch i { |
case RTAX_IFA: |
sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa))) |
if err != nil { |
return nil |
} |
sas = append(sas, sa) |
case RTAX_NETMASK: |
if rsa.Family == AF_UNSPEC { |
rsa.Family = AF_INET // an old fasion, AF_UNSPEC means AF_INET |
} |
sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa))) |
if err != nil { |
return nil |
} |
sas = append(sas, sa) |
case RTAX_BRD: |
// nothing to do |
} |
buf = buf[rsaAlignOf(int(rsa.Len)):] |
} |
|
return sas |
} |
|
// ParseRoutingMessage parses buf as routing messages and returns |
// the slice containing the RoutingMessage interfaces. |
func ParseRoutingMessage(buf []byte) (msgs []RoutingMessage, err error) { |
for len(buf) >= anyMessageLen { |
any := (*anyMessage)(unsafe.Pointer(&buf[0])) |
if any.Version != RTM_VERSION { |
return nil, EINVAL |
} |
msgs = append(msgs, any.toRoutingMessage(buf)) |
buf = buf[any.Msglen:] |
} |
return msgs, nil |
} |
|
// ParseRoutingMessage parses msg's payload as raw sockaddrs and |
// returns the slice containing the Sockaddr interfaces. |
func ParseRoutingSockaddr(msg RoutingMessage) (sas []Sockaddr, err error) { |
return append(sas, msg.sockaddr()...), nil |
} |
/libcall_uname.go
0,0 → 1,8
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
//sysnb Uname(buf *Utsname) (err error) |
//uname(buf *Utsname) int |
/route_freebsd.go
0,0 → 1,77
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// Routing sockets and messages for FreeBSD |
|
package syscall |
|
import ( |
"unsafe" |
) |
|
func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage { |
switch any.Type { |
case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE: |
p := (*RouteMessage)(unsafe.Pointer(any)) |
rtm := &RouteMessage{} |
rtm.Header = p.Header |
rtm.Data = buf[SizeofRtMsghdr:any.Msglen] |
return rtm |
case RTM_IFINFO: |
p := (*InterfaceMessage)(unsafe.Pointer(any)) |
ifm := &InterfaceMessage{} |
ifm.Header = p.Header |
ifm.Data = buf[SizeofIfMsghdr:any.Msglen] |
return ifm |
case RTM_NEWADDR, RTM_DELADDR: |
p := (*InterfaceAddrMessage)(unsafe.Pointer(any)) |
ifam := &InterfaceAddrMessage{} |
ifam.Header = p.Header |
ifam.Data = buf[SizeofIfaMsghdr:any.Msglen] |
return ifam |
case RTM_NEWMADDR, RTM_DELMADDR: |
p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any)) |
ifmam := &InterfaceMulticastAddrMessage{} |
ifmam.Header = p.Header |
ifmam.Data = buf[SizeofIfmaMsghdr:any.Msglen] |
return ifmam |
} |
return nil |
} |
|
// InterfaceMulticastAddrMessage represents a routing message |
// containing network interface address entries. |
type InterfaceMulticastAddrMessage struct { |
Header IfmaMsghdr |
Data []byte |
} |
|
const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA |
|
func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) { |
if m.Header.Addrs&rtaIfmaMask == 0 { |
return nil |
} |
|
buf := m.Data[:] |
for i := uint(0); i < RTAX_MAX; i++ { |
if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 { |
continue |
} |
rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0])) |
switch i { |
case RTAX_IFA: |
sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa))) |
if e != nil { |
return nil |
} |
sas = append(sas, sa) |
case RTAX_GATEWAY, RTAX_IFP: |
// nothing to do |
} |
buf = buf[rsaAlignOf(int(rsa.Len)):] |
} |
|
return sas |
} |
/socket.go
0,0 → 1,411
// socket.go -- Socket handling. |
|
// Copyright 2009 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// Low-level socket interface. |
// Only for implementing net package. |
// DO NOT USE DIRECTLY. |
|
package syscall |
|
import "unsafe" |
|
// For testing: clients can set this flag to force |
// creation of IPv6 sockets to return EAFNOSUPPORT. |
var SocketDisableIPv6 bool |
|
type Sockaddr interface { |
sockaddr() (ptr *RawSockaddrAny, len Socklen_t, err error) // lowercase; only we can define Sockaddrs |
} |
|
type RawSockaddrAny struct { |
Addr RawSockaddr |
Pad [12]int8 |
} |
|
const SizeofSockaddrAny = 0x1c |
|
type SockaddrInet4 struct { |
Port int |
Addr [4]byte |
raw RawSockaddrInet4 |
} |
|
func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, error) { |
if sa.Port < 0 || sa.Port > 0xFFFF { |
return nil, 0, EINVAL |
} |
sa.raw.Family = AF_INET |
n := sa.raw.setLen() |
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) |
p[0] = byte(sa.Port >> 8) |
p[1] = byte(sa.Port) |
for i := 0; i < len(sa.Addr); i++ { |
sa.raw.Addr[i] = sa.Addr[i] |
} |
return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, nil |
} |
|
type SockaddrInet6 struct { |
Port int |
ZoneId uint32 |
Addr [16]byte |
raw RawSockaddrInet6 |
} |
|
func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, error) { |
if sa.Port < 0 || sa.Port > 0xFFFF { |
return nil, 0, EINVAL |
} |
sa.raw.Family = AF_INET6 |
n := sa.raw.setLen() |
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) |
p[0] = byte(sa.Port >> 8) |
p[1] = byte(sa.Port) |
sa.raw.Scope_id = sa.ZoneId |
for i := 0; i < len(sa.Addr); i++ { |
sa.raw.Addr[i] = sa.Addr[i] |
} |
return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, nil |
} |
|
type SockaddrUnix struct { |
Name string |
raw RawSockaddrUnix |
} |
|
func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, error) { |
name := sa.Name |
n := len(name) |
if n >= len(sa.raw.Path) || n == 0 { |
return nil, 0, EINVAL |
} |
sa.raw.Family = AF_UNIX |
sa.raw.setLen(n) |
for i := 0; i < n; i++ { |
sa.raw.Path[i] = int8(name[i]) |
} |
if sa.raw.Path[0] == '@' { |
sa.raw.Path[0] = 0 |
} |
|
// length is family (uint16), name, NUL. |
return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), 2 + Socklen_t(n) + 1, nil |
} |
|
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { |
switch rsa.Addr.Family { |
case AF_UNIX: |
pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) |
sa := new(SockaddrUnix) |
n, err := pp.getLen() |
if err != nil { |
return nil, err |
} |
bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0])) |
sa.Name = string(bytes[0:n]) |
return sa, nil |
|
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, nil |
|
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, nil |
} |
return anyToSockaddrOS(rsa) |
} |
|
//sys accept(fd int, sa *RawSockaddrAny, len *Socklen_t) (nfd int, err error) |
//accept(fd int, sa *RawSockaddrAny, len *Socklen_t) int |
|
func Accept(fd int) (nfd int, sa Sockaddr, err error) { |
var rsa RawSockaddrAny |
var len Socklen_t = SizeofSockaddrAny |
nfd, err = accept(fd, &rsa, &len) |
if err != nil { |
return |
} |
sa, err = anyToSockaddr(&rsa) |
if err != nil { |
Close(nfd) |
nfd = 0 |
} |
return |
} |
|
//sysnb getsockname(fd int, sa *RawSockaddrAny, len *Socklen_t) (err error) |
//getsockname(fd int, sa *RawSockaddrAny, len *Socklen_t) int |
|
func Getsockname(fd int) (sa Sockaddr, err error) { |
var rsa RawSockaddrAny |
var len Socklen_t = SizeofSockaddrAny |
if err = getsockname(fd, &rsa, &len); err != nil { |
return |
} |
return anyToSockaddr(&rsa) |
} |
|
//sysnb getpeername(fd int, sa *RawSockaddrAny, len *Socklen_t) (err error) |
//getpeername(fd int, sa *RawSockaddrAny, len *Socklen_t) int |
|
func Getpeername(fd int) (sa Sockaddr, err error) { |
var rsa RawSockaddrAny |
var len Socklen_t = SizeofSockaddrAny |
if err = getpeername(fd, &rsa, &len); err != nil { |
return |
} |
return anyToSockaddr(&rsa) |
} |
|
//sys bind(fd int, sa *RawSockaddrAny, len Socklen_t) (err error) |
//bind(fd int, sa *RawSockaddrAny, len Socklen_t) int |
|
func Bind(fd int, sa Sockaddr) (err error) { |
ptr, n, err := sa.sockaddr() |
if err != nil { |
return err |
} |
return bind(fd, ptr, n) |
} |
|
//sys connect(s int, addr *RawSockaddrAny, addrlen Socklen_t) (err error) |
//connect(s int, addr *RawSockaddrAny, addrlen Socklen_t) int |
|
func Connect(fd int, sa Sockaddr) (err error) { |
ptr, n, err := sa.sockaddr() |
if err != nil { |
return err |
} |
return connect(fd, ptr, n) |
} |
|
//sysnb socket(domain int, typ int, proto int) (fd int, err error) |
//socket(domain int, typ int, protocol int) int |
|
func Socket(domain, typ, proto int) (fd int, err error) { |
if domain == AF_INET6 && SocketDisableIPv6 { |
return -1, EAFNOSUPPORT |
} |
fd, err = socket(domain, typ, proto) |
return |
} |
|
//sysnb socketpair(domain int, typ int, proto int, fd *[2]int) (err error) |
//socketpair(domain int, typ int, protocol int, fd *[2]int) int |
|
func Socketpair(domain, typ, proto int) (fd [2]int, err error) { |
err = socketpair(domain, typ, proto, &fd) |
return |
} |
|
//sys getsockopt(s int, level int, name int, val uintptr, vallen *Socklen_t) (err error) |
//getsockopt(s int, level int, name int, val *byte, vallen *Socklen_t) int |
|
func GetsockoptInt(fd, level, opt int) (value int, err error) { |
var n int32 |
vallen := Socklen_t(4) |
err = getsockopt(fd, level, opt, (uintptr)(unsafe.Pointer(&n)), &vallen) |
return int(n), err |
} |
|
func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) { |
vallen := Socklen_t(4) |
err = getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value[0])), &vallen) |
return value, err |
} |
|
func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) { |
var value IPMreq |
vallen := Socklen_t(SizeofIPMreq) |
err := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen) |
return &value, err |
} |
|
func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) { |
var value IPMreqn |
vallen := Socklen_t(SizeofIPMreqn) |
err := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen) |
return &value, err |
} |
|
func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) { |
var value IPv6Mreq |
vallen := Socklen_t(SizeofIPv6Mreq) |
err := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen) |
return &value, err |
} |
|
//sys setsockopt(s int, level int, name int, val *byte, vallen Socklen_t) (err error) |
//setsockopt(s int, level int, optname int, val *byte, vallen Socklen_t) int |
|
func SetsockoptInt(fd, level, opt int, value int) (err error) { |
var n = int32(value) |
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&n)), 4) |
} |
|
func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) { |
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&value[0])), 4) |
} |
|
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) { |
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(tv)), Socklen_t(unsafe.Sizeof(*tv))) |
} |
|
type Linger struct { |
Onoff int32 |
Linger int32 |
} |
|
func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) { |
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(l)), Socklen_t(unsafe.Sizeof(*l))) |
} |
|
func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) { |
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(mreq)), Socklen_t(unsafe.Sizeof(*mreq))) |
} |
|
func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) { |
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(mreq)), Socklen_t(unsafe.Sizeof(*mreq))) |
} |
|
func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) { |
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(mreq)), Socklen_t(unsafe.Sizeof(*mreq))) |
} |
|
func SetsockoptString(fd, level, opt int, s string) (err error) { |
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&[]byte(s)[0])), Socklen_t(len(s))) |
} |
|
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *Socklen_t) (n int, err error) |
//recvfrom(fd int, buf *byte, len Size_t, flags int, from *RawSockaddrAny, fromlen *Socklen_t) Ssize_t |
|
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { |
var rsa RawSockaddrAny |
var len Socklen_t = SizeofSockaddrAny |
if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil { |
return |
} |
from, err = anyToSockaddr(&rsa) |
return |
} |
|
//sys sendto(s int, buf []byte, flags int, to *RawSockaddrAny, tolen Socklen_t) (err error) |
//sendto(s int, buf *byte, len Size_t, flags int, to *RawSockaddrAny, tolen Socklen_t) Ssize_t |
|
func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) { |
ptr, n, err := to.sockaddr() |
if err != nil { |
return err |
} |
return sendto(fd, p, flags, ptr, n) |
} |
|
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) |
//recvmsg(s int, msg *Msghdr, flags int) Ssize_t |
|
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { |
var msg Msghdr |
var rsa RawSockaddrAny |
msg.Name = (*byte)(unsafe.Pointer(&rsa)) |
msg.Namelen = uint32(SizeofSockaddrAny) |
var iov Iovec |
if len(p) > 0 { |
iov.Base = (*byte)(unsafe.Pointer(&p[0])) |
iov.SetLen(len(p)) |
} |
var dummy byte |
if len(oob) > 0 { |
// receive at least one normal byte |
if len(p) == 0 { |
iov.Base = &dummy |
iov.SetLen(1) |
} |
msg.Control = (*byte)(unsafe.Pointer(&oob[0])) |
msg.SetControllen(len(oob)) |
} |
msg.Iov = &iov |
msg.Iovlen = 1 |
if n, err = recvmsg(fd, &msg, flags); err != nil { |
return |
} |
oobn = int(msg.Controllen) |
recvflags = int(msg.Flags) |
// source address is only specified if the socket is unconnected |
if rsa.Addr.Family != AF_UNSPEC { |
from, err = anyToSockaddr(&rsa) |
} |
return |
} |
|
//sys sendmsg(s int, msg *Msghdr, flags int) (err error) |
//sendmsg(s int, msg *Msghdr, flags int) Ssize_t |
|
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { |
var ptr *RawSockaddrAny |
var salen Socklen_t |
if to != nil { |
var err error |
ptr, salen, err = to.sockaddr() |
if err != nil { |
return err |
} |
} |
var msg Msghdr |
msg.Name = (*byte)(unsafe.Pointer(ptr)) |
msg.Namelen = uint32(salen) |
var iov Iovec |
if len(p) > 0 { |
iov.Base = (*byte)(unsafe.Pointer(&p[0])) |
iov.SetLen(len(p)) |
} |
var dummy byte |
if len(oob) > 0 { |
// send at least one normal byte |
if len(p) == 0 { |
iov.Base = &dummy |
iov.SetLen(1) |
} |
msg.Control = (*byte)(unsafe.Pointer(&oob[0])) |
msg.SetControllen(len(oob)) |
} |
msg.Iov = &iov |
msg.Iovlen = 1 |
if err = sendmsg(fd, &msg, flags); err != nil { |
return |
} |
return |
} |
|
//sys Listen(fd int, n int) (err error) |
//listen(fd int, n int) int |
|
//sys Shutdown(fd int, how int) (err error) |
//shutdown(fd int, how int) int |
|
func (iov *Iovec) SetLen(length int) { |
iov.Len = Iovec_len_t(length) |
} |
|
func (msghdr *Msghdr) SetControllen(length int) { |
msghdr.Controllen = Msghdr_controllen_t(length) |
} |
|
func (cmsg *Cmsghdr) SetLen(length int) { |
cmsg.Len = Cmsghdr_len_t(length) |
} |
/syscall_linux_386.go
0,0 → 1,25
// syscall_linux_386.go -- GNU/Linux 386 specific support |
|
// Copyright 2009 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
import "unsafe" |
|
func (r *PtraceRegs) PC() uint64 { |
return uint64(uint32(r.Eip)) |
} |
|
func (r *PtraceRegs) SetPC(pc uint64) { |
r.Eip = int32(pc) |
} |
|
func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) { |
return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout))) |
} |
|
func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) { |
return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) |
} |
/syscall_stubs.go
0,0 → 1,27
// Copyright 2010 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// These are stubs. |
|
package syscall |
|
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) { |
z := -1 |
return uintptr(z), 0, uintptr(ENOSYS) |
} |
|
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { |
z := -1 |
return uintptr(z), 0, uintptr(ENOSYS) |
} |
|
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) { |
z := -1 |
return uintptr(z), 0, uintptr(ENOSYS) |
} |
|
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { |
z := -1 |
return uintptr(z), 0, uintptr(ENOSYS) |
} |
/env_unix.go
0,0 → 1,109
// Copyright 2010 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// +build darwin freebsd linux netbsd openbsd |
|
// Unix environment variables. |
|
package syscall |
|
import "sync" |
|
var ( |
// envOnce guards initialization by copyenv, which populates env. |
envOnce sync.Once |
|
// envLock guards env and envs. |
envLock sync.RWMutex |
|
// env maps from an environment variable to its first occurrence in envs. |
env map[string]int |
|
// envs is provided by the runtime. elements are expected to be |
// of the form "key=value". |
Envs []string |
) |
|
// setenv_c is provided by the runtime, but is a no-op if cgo isn't |
// loaded. |
func setenv_c(k, v string) |
|
func copyenv() { |
env = make(map[string]int) |
for i, s := range Envs { |
for j := 0; j < len(s); j++ { |
if s[j] == '=' { |
key := s[:j] |
if _, ok := env[key]; !ok { |
env[key] = i |
} |
break |
} |
} |
} |
} |
|
func Getenv(key string) (value string, found bool) { |
envOnce.Do(copyenv) |
if len(key) == 0 { |
return "", false |
} |
|
envLock.RLock() |
defer envLock.RUnlock() |
|
i, ok := env[key] |
if !ok { |
return "", false |
} |
s := Envs[i] |
for i := 0; i < len(s); i++ { |
if s[i] == '=' { |
return s[i+1:], true |
} |
} |
return "", false |
} |
|
func Setenv(key, value string) error { |
envOnce.Do(copyenv) |
if len(key) == 0 { |
return EINVAL |
} |
|
envLock.Lock() |
defer envLock.Unlock() |
|
i, ok := env[key] |
kv := key + "=" + value |
if ok { |
Envs[i] = kv |
} else { |
i = len(Envs) |
Envs = append(Envs, kv) |
} |
env[key] = i |
setenv_c(key, value) |
return nil |
} |
|
func Clearenv() { |
envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv |
|
envLock.Lock() |
defer envLock.Unlock() |
|
env = make(map[string]int) |
Envs = []string{} |
// TODO(bradfitz): pass through to C |
} |
|
func Environ() []string { |
envOnce.Do(copyenv) |
envLock.RLock() |
defer envLock.RUnlock() |
a := make([]string, len(Envs)) |
copy(a, Envs) |
return a |
} |
/libcall_irix.go
0,0 → 1,8
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno) |
//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long |
/syscall_linux_alpha.go
0,0 → 1,57
// syscall_linux_alpha.go -- GNU/Linux ALPHA specific support |
|
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
import "unsafe" |
|
type PtraceRegs struct { |
R0 uint64 |
R1 uint64 |
R2 uint64 |
R3 uint64 |
R4 uint64 |
R5 uint64 |
R6 uint64 |
R7 uint64 |
R8 uint64 |
R19 uint64 |
R20 uint64 |
R21 uint64 |
R22 uint64 |
R23 uint64 |
R24 uint64 |
R25 uint64 |
R26 uint64 |
R27 uint64 |
R28 uint64 |
Hae uint64 |
Trap_a0 uint64 |
Trap_a1 uint64 |
Trap_a2 uint64 |
Ps uint64 |
Pc uint64 |
Gp uint64 |
R16 uint64 |
R17 uint64 |
R18 uint64 |
} |
|
func (r *PtraceRegs) PC() uint64 { |
return r.Pc |
} |
|
func (r *PtraceRegs) SetPC(pc uint64) { |
r.Pc = pc |
} |
|
func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) { |
return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout))) |
} |
|
func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) { |
return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) |
} |
/exec_windows.go
0,0 → 1,327
// Copyright 2009 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// Fork, exec, wait, etc. |
|
package syscall |
|
import ( |
"sync" |
"unicode/utf16" |
"unsafe" |
) |
|
var ForkLock sync.RWMutex |
|
// EscapeArg rewrites command line argument s as prescribed |
// in http://msdn.microsoft.com/en-us/library/ms880421. |
// This function returns "" (2 double quotes) if s is empty. |
// Alternatively, these transformations are done: |
// - every back slash (\) is doubled, but only if immediately |
// followed by double quote ("); |
// - every double quote (") is escaped by back slash (\); |
// - finally, s is wrapped with double quotes (arg -> "arg"), |
// but only if there is space or tab inside s. |
func EscapeArg(s string) string { |
if len(s) == 0 { |
return "\"\"" |
} |
n := len(s) |
hasSpace := false |
for i := 0; i < len(s); i++ { |
switch s[i] { |
case '"', '\\': |
n++ |
case ' ', '\t': |
hasSpace = true |
} |
} |
if hasSpace { |
n += 2 |
} |
if n == len(s) { |
return s |
} |
|
qs := make([]byte, n) |
j := 0 |
if hasSpace { |
qs[j] = '"' |
j++ |
} |
slashes := 0 |
for i := 0; i < len(s); i++ { |
switch s[i] { |
default: |
slashes = 0 |
qs[j] = s[i] |
case '\\': |
slashes++ |
qs[j] = s[i] |
case '"': |
for ; slashes > 0; slashes-- { |
qs[j] = '\\' |
j++ |
} |
qs[j] = '\\' |
j++ |
qs[j] = s[i] |
} |
j++ |
} |
if hasSpace { |
for ; slashes > 0; slashes-- { |
qs[j] = '\\' |
j++ |
} |
qs[j] = '"' |
j++ |
} |
return string(qs[:j]) |
} |
|
// makeCmdLine builds a command line out of args by escaping "special" |
// characters and joining the arguments with spaces. |
func makeCmdLine(args []string) string { |
var s string |
for _, v := range args { |
if s != "" { |
s += " " |
} |
s += EscapeArg(v) |
} |
return s |
} |
|
// createEnvBlock converts an array of environment strings into |
// the representation required by CreateProcess: a sequence of NUL |
// terminated strings followed by a nil. |
// Last bytes are two UCS-2 NULs, or four NUL bytes. |
func createEnvBlock(envv []string) *uint16 { |
if len(envv) == 0 { |
return &utf16.Encode([]rune("\x00\x00"))[0] |
} |
length := 0 |
for _, s := range envv { |
length += len(s) + 1 |
} |
length += 1 |
|
b := make([]byte, length) |
i := 0 |
for _, s := range envv { |
l := len(s) |
copy(b[i:i+l], []byte(s)) |
copy(b[i+l:i+l+1], []byte{0}) |
i = i + l + 1 |
} |
copy(b[i:i+1], []byte{0}) |
|
return &utf16.Encode([]rune(string(b)))[0] |
} |
|
func CloseOnExec(fd Handle) { |
SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0) |
} |
|
func SetNonblock(fd Handle, nonblocking bool) (err error) { |
return nil |
} |
|
// getFullPath retrieves the full path of the specified file. |
// Just a wrapper for Windows GetFullPathName api. |
func getFullPath(name string) (path string, err error) { |
p := StringToUTF16Ptr(name) |
buf := make([]uint16, 100) |
n, err := GetFullPathName(p, uint32(len(buf)), &buf[0], nil) |
if err != nil { |
return "", err |
} |
if n > uint32(len(buf)) { |
// Windows is asking for bigger buffer. |
buf = make([]uint16, n) |
n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil) |
if err != nil { |
return "", err |
} |
if n > uint32(len(buf)) { |
return "", EINVAL |
} |
} |
return UTF16ToString(buf[:n]), nil |
} |
|
func isSlash(c uint8) bool { |
return c == '\\' || c == '/' |
} |
|
func normalizeDir(dir string) (name string, err error) { |
ndir, err := getFullPath(dir) |
if err != nil { |
return "", err |
} |
if len(ndir) > 2 && isSlash(ndir[0]) && isSlash(ndir[1]) { |
// dir cannot have \\server\share\path form |
return "", EINVAL |
} |
return ndir, nil |
} |
|
func volToUpper(ch int) int { |
if 'a' <= ch && ch <= 'z' { |
ch += 'A' - 'a' |
} |
return ch |
} |
|
func joinExeDirAndFName(dir, p string) (name string, err error) { |
if len(p) == 0 { |
return "", EINVAL |
} |
if len(p) > 2 && isSlash(p[0]) && isSlash(p[1]) { |
// \\server\share\path form |
return p, nil |
} |
if len(p) > 1 && p[1] == ':' { |
// has drive letter |
if len(p) == 2 { |
return "", EINVAL |
} |
if isSlash(p[2]) { |
return p, nil |
} else { |
d, err := normalizeDir(dir) |
if err != nil { |
return "", err |
} |
if volToUpper(int(p[0])) == volToUpper(int(d[0])) { |
return getFullPath(d + "\\" + p[2:]) |
} else { |
return getFullPath(p) |
} |
} |
} else { |
// no drive letter |
d, err := normalizeDir(dir) |
if err != nil { |
return "", err |
} |
if isSlash(p[0]) { |
return getFullPath(d[:2] + p) |
} else { |
return getFullPath(d + "\\" + p) |
} |
} |
// we shouldn't be here |
return "", EINVAL |
} |
|
type ProcAttr struct { |
Dir string |
Env []string |
Files []Handle |
Sys *SysProcAttr |
} |
|
type SysProcAttr struct { |
HideWindow bool |
CmdLine string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess |
} |
|
var zeroProcAttr ProcAttr |
var zeroSysProcAttr SysProcAttr |
|
func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) { |
if len(argv0) == 0 { |
return 0, 0, EWINDOWS |
} |
if attr == nil { |
attr = &zeroProcAttr |
} |
sys := attr.Sys |
if sys == nil { |
sys = &zeroSysProcAttr |
} |
|
if len(attr.Files) > 3 { |
return 0, 0, EWINDOWS |
} |
|
if len(attr.Dir) != 0 { |
// StartProcess assumes that argv0 is relative to attr.Dir, |
// because it implies Chdir(attr.Dir) before executing argv0. |
// Windows CreateProcess assumes the opposite: it looks for |
// argv0 relative to the current directory, and, only once the new |
// process is started, it does Chdir(attr.Dir). We are adjusting |
// for that difference here by making argv0 absolute. |
var err error |
argv0, err = joinExeDirAndFName(attr.Dir, argv0) |
if err != nil { |
return 0, 0, err |
} |
} |
argv0p := StringToUTF16Ptr(argv0) |
|
var cmdline string |
// Windows CreateProcess takes the command line as a single string: |
// use attr.CmdLine if set, else build the command line by escaping |
// and joining each argument with spaces |
if sys.CmdLine != "" { |
cmdline = sys.CmdLine |
} else { |
cmdline = makeCmdLine(argv) |
} |
|
var argvp *uint16 |
if len(cmdline) != 0 { |
argvp = StringToUTF16Ptr(cmdline) |
} |
|
var dirp *uint16 |
if len(attr.Dir) != 0 { |
dirp = StringToUTF16Ptr(attr.Dir) |
} |
|
// Acquire the fork lock so that no other threads |
// create new fds that are not yet close-on-exec |
// before we fork. |
ForkLock.Lock() |
defer ForkLock.Unlock() |
|
p, _ := GetCurrentProcess() |
fd := make([]Handle, len(attr.Files)) |
for i := range attr.Files { |
if attr.Files[i] > 0 { |
err := DuplicateHandle(p, Handle(attr.Files[i]), p, &fd[i], 0, true, DUPLICATE_SAME_ACCESS) |
if err != nil { |
return 0, 0, err |
} |
defer CloseHandle(Handle(fd[i])) |
} |
} |
si := new(StartupInfo) |
si.Cb = uint32(unsafe.Sizeof(*si)) |
si.Flags = STARTF_USESTDHANDLES |
if sys.HideWindow { |
si.Flags |= STARTF_USESHOWWINDOW |
si.ShowWindow = SW_HIDE |
} |
si.StdInput = fd[0] |
si.StdOutput = fd[1] |
si.StdErr = fd[2] |
|
pi := new(ProcessInformation) |
|
err = CreateProcess(argv0p, argvp, nil, nil, true, CREATE_UNICODE_ENVIRONMENT, createEnvBlock(attr.Env), dirp, si, pi) |
if err != nil { |
return 0, 0, err |
} |
defer CloseHandle(Handle(pi.Thread)) |
|
return int(pi.ProcessId), uintptr(pi.Process), nil |
} |
|
func Exec(argv0 string, argv []string, envv []string) (err error) { |
return EWINDOWS |
} |
/libcall_posix_largefile.go
0,0 → 1,37
// Copyright 2009 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// POSIX library calls on systems which use the largefile interface. |
|
package syscall |
|
//sys Fstat(fd int, stat *Stat_t) (err error) |
//fstat64(fd int, stat *Stat_t) int |
|
//sys Ftruncate(fd int, length int64) (err error) |
//ftruncate64(fd int, length Offset_t) int |
|
//sys Lstat(path string, stat *Stat_t) (err error) |
//lstat64(path *byte, stat *Stat_t) int |
|
//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) |
//mmap64(addr *byte, length Size_t, prot int, flags int, fd int, offset Offset_t) *byte |
|
//sys Open(path string, mode int, perm uint32) (fd int, err error) |
//open64(path *byte, mode int, perm Mode_t) int |
|
//sys Pread(fd int, p []byte, offset int64) (n int, err error) |
//pread64(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t |
|
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) |
//pwrite64(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t |
|
//sys Seek(fd int, offset int64, whence int) (off int64, err error) |
//lseek64(fd int, offset Offset_t, whence int) Offset_t |
|
//sys Stat(path string, stat *Stat_t) (err error) |
//stat64(path *byte, stat *Stat_t) int |
|
//sys Truncate(path string, length int64) (err error) |
//truncate64(path *byte, length Offset_t) int |
/bpf_bsd.go
0,0 → 1,169
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// +build darwin freebsd netbsd openbsd |
|
// Berkeley packet filter for BSD variants |
|
package syscall |
|
import ( |
"unsafe" |
) |
|
func BpfStmt(code, k int) *BpfInsn { |
return &BpfInsn{Code: uint16(code), K: uint32(k)} |
} |
|
func BpfJump(code, k, jt, jf int) *BpfInsn { |
return &BpfInsn{Code: uint16(code), Jt: uint8(jt), Jf: uint8(jf), K: uint32(k)} |
} |
|
func BpfBuflen(fd int) (int, error) { |
var l int |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGBLEN, uintptr(unsafe.Pointer(&l))) |
if err != 0 { |
return 0, Errno(err) |
} |
return l, nil |
} |
|
func SetBpfBuflen(fd, l int) (int, error) { |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSBLEN, uintptr(unsafe.Pointer(&l))) |
if err != 0 { |
return 0, Errno(err) |
} |
return l, nil |
} |
|
func BpfDatalink(fd int) (int, error) { |
var t int |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGDLT, uintptr(unsafe.Pointer(&t))) |
if err != 0 { |
return 0, Errno(err) |
} |
return t, nil |
} |
|
func SetBpfDatalink(fd, t int) (int, error) { |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSDLT, uintptr(unsafe.Pointer(&t))) |
if err != 0 { |
return 0, Errno(err) |
} |
return t, nil |
} |
|
func SetBpfPromisc(fd, m int) error { |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCPROMISC, uintptr(unsafe.Pointer(&m))) |
if err != 0 { |
return Errno(err) |
} |
return nil |
} |
|
func FlushBpf(fd int) error { |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCFLUSH, 0) |
if err != 0 { |
return Errno(err) |
} |
return nil |
} |
|
type ivalue struct { |
name [IFNAMSIZ]byte |
value int16 |
} |
|
func BpfInterface(fd int, name string) (string, error) { |
var iv ivalue |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGETIF, uintptr(unsafe.Pointer(&iv))) |
if err != 0 { |
return "", Errno(err) |
} |
return name, nil |
} |
|
func SetBpfInterface(fd int, name string) error { |
var iv ivalue |
copy(iv.name[:], []byte(name)) |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETIF, uintptr(unsafe.Pointer(&iv))) |
if err != 0 { |
return Errno(err) |
} |
return nil |
} |
|
func BpfTimeout(fd int) (*Timeval, error) { |
var tv Timeval |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGRTIMEOUT, uintptr(unsafe.Pointer(&tv))) |
if err != 0 { |
return nil, Errno(err) |
} |
return &tv, nil |
} |
|
func SetBpfTimeout(fd int, tv *Timeval) error { |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSRTIMEOUT, uintptr(unsafe.Pointer(tv))) |
if err != 0 { |
return Errno(err) |
} |
return nil |
} |
|
func BpfStats(fd int) (*BpfStat, error) { |
var s BpfStat |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGSTATS, uintptr(unsafe.Pointer(&s))) |
if err != 0 { |
return nil, Errno(err) |
} |
return &s, nil |
} |
|
func SetBpfImmediate(fd, m int) error { |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCIMMEDIATE, uintptr(unsafe.Pointer(&m))) |
if err != 0 { |
return Errno(err) |
} |
return nil |
} |
|
func SetBpf(fd int, i []BpfInsn) error { |
var p BpfProgram |
p.Len = uint32(len(i)) |
p.Insns = (*BpfInsn)(unsafe.Pointer(&i[0])) |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETF, uintptr(unsafe.Pointer(&p))) |
if err != 0 { |
return Errno(err) |
} |
return nil |
} |
|
func CheckBpfVersion(fd int) error { |
var v BpfVersion |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCVERSION, uintptr(unsafe.Pointer(&v))) |
if err != 0 { |
return Errno(err) |
} |
if v.Major != BPF_MAJOR_VERSION || v.Minor != BPF_MINOR_VERSION { |
return EINVAL |
} |
return nil |
} |
|
func BpfHeadercmpl(fd int) (int, error) { |
var f int |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGHDRCMPLT, uintptr(unsafe.Pointer(&f))) |
if err != 0 { |
return 0, Errno(err) |
} |
return f, nil |
} |
|
func SetBpfHeadercmpl(fd, f int) error { |
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSHDRCMPLT, uintptr(unsafe.Pointer(&f))) |
if err != 0 { |
return Errno(err) |
} |
return nil |
} |
/libcall_solaris_sparc64.go
0,0 → 1,10
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
// 64-bit ptrace(3C) doesn't exist |
func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno { |
return ENOSYS |
} |
/errstr_linux.go
0,0 → 1,23
// errstr_rtems.go -- RTEMS specific error strings. |
|
// Copyright 2010 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
import "unsafe" |
|
//sysnb strerror_r(errnum int, b []byte) (errstr *byte) |
//strerror_r(errnum int, b *byte, len Size_t) *byte |
|
func Errstr(errnum int) string { |
a := make([]byte, 128) |
p := strerror_r(errnum, a) |
b := (*[1000]byte)(unsafe.Pointer(p)) |
i := 0 |
for b[i] != 0 { |
i++ |
} |
return string(b[:i]) |
} |
/route_darwin.go
0,0 → 1,77
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// Routing sockets and messages for Darwin |
|
package syscall |
|
import ( |
"unsafe" |
) |
|
func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage { |
switch any.Type { |
case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE: |
p := (*RouteMessage)(unsafe.Pointer(any)) |
rtm := &RouteMessage{} |
rtm.Header = p.Header |
rtm.Data = buf[SizeofRtMsghdr:any.Msglen] |
return rtm |
case RTM_IFINFO: |
p := (*InterfaceMessage)(unsafe.Pointer(any)) |
ifm := &InterfaceMessage{} |
ifm.Header = p.Header |
ifm.Data = buf[SizeofIfMsghdr:any.Msglen] |
return ifm |
case RTM_NEWADDR, RTM_DELADDR: |
p := (*InterfaceAddrMessage)(unsafe.Pointer(any)) |
ifam := &InterfaceAddrMessage{} |
ifam.Header = p.Header |
ifam.Data = buf[SizeofIfaMsghdr:any.Msglen] |
return ifam |
case RTM_NEWMADDR2, RTM_DELMADDR: |
p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any)) |
ifmam := &InterfaceMulticastAddrMessage{} |
ifmam.Header = p.Header |
ifmam.Data = buf[SizeofIfmaMsghdr2:any.Msglen] |
return ifmam |
} |
return nil |
} |
|
// InterfaceMulticastAddrMessage represents a routing message |
// containing network interface address entries. |
type InterfaceMulticastAddrMessage struct { |
Header IfmaMsghdr2 |
Data []byte |
} |
|
const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA |
|
func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) { |
if m.Header.Addrs&rtaIfmaMask == 0 { |
return nil |
} |
|
buf := m.Data[:] |
for i := uint(0); i < RTAX_MAX; i++ { |
if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 { |
continue |
} |
rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0])) |
switch i { |
case RTAX_IFA: |
sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa))) |
if e != nil { |
return nil |
} |
sas = append(sas, sa) |
case RTAX_GATEWAY, RTAX_IFP: |
// nothing to do |
} |
buf = buf[rsaAlignOf(int(rsa.Len)):] |
} |
|
return sas |
} |
/errno.c
0,0 → 1,26
/* errno.c -- functions for getting and setting errno |
|
Copyright 2010 The Go Authors. All rights reserved. |
Use of this source code is governed by a BSD-style |
license that can be found in the LICENSE file. */ |
|
#include <errno.h> |
#include <stdint.h> |
|
/* errno is typically a macro. These functions set |
and get errno specific to the libc being used. */ |
|
uintptr_t GetErrno() asm ("libgo_syscall.syscall.GetErrno"); |
void SetErrno(uintptr_t) asm ("libgo_syscall.syscall.SetErrno"); |
|
uintptr_t |
GetErrno() |
{ |
return (uintptr_t) errno; |
} |
|
void |
SetErrno(uintptr_t value) |
{ |
errno = (int) value; |
} |
/exec_linux.go
0,0 → 1,248
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// +build linux |
|
package syscall |
|
import ( |
"unsafe" |
) |
|
//sysnb raw_prctl(option int, arg2 int, arg3 int, arg4 int, arg5 int) (ret int, err Errno) |
//prctl(option int, arg2 _C_long, arg3 _C_long, arg4 _C_long, arg5 _C_long) int |
|
type SysProcAttr struct { |
Chroot string // Chroot. |
Credential *Credential // Credential. |
Ptrace bool // Enable tracing. |
Setsid bool // Create session. |
Setpgid bool // Set process group ID to new pid (SYSV setpgrp) |
Setctty bool // Set controlling terminal to fd 0 |
Noctty bool // Detach fd 0 from controlling terminal |
Pdeathsig int // Signal that the process will get when its parent dies (Linux only) |
} |
|
// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child. |
// If a dup or exec fails, write the errno error to pipe. |
// (Pipe is close-on-exec so if exec succeeds, it will be closed.) |
// In the child, this function must not acquire any locks, because |
// they might have been locked at the time of the fork. This means |
// no rescheduling, no malloc calls, and no new stack segments. |
// The calls to RawSyscall are okay because they are assembly |
// functions that do not grow the stack. |
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) { |
// Declare all variables at top in case any |
// declarations require heap allocation (e.g., err1). |
var ( |
r1 Pid_t |
err1 Errno |
nextfd int |
i int |
) |
|
// guard against side effects of shuffling fds below. |
fd := append([]int(nil), attr.Files...) |
|
// About to call fork. |
// No more allocation or calls of non-assembly functions. |
r1, err1 = raw_fork() |
if err1 != 0 { |
return 0, err1 |
} |
|
if r1 != 0 { |
// parent; return PID |
return int(r1), 0 |
} |
|
// Fork succeeded, now in child. |
|
// Parent death signal |
if sys.Pdeathsig != 0 { |
_, err1 = raw_prctl(PR_SET_PDEATHSIG, sys.Pdeathsig, 0, 0, 0) |
if err1 != 0 { |
goto childerror |
} |
|
// Signal self if parent is already dead. This might cause a |
// duplicate signal in rare cases, but it won't matter when |
// using SIGKILL. |
ppid := Getppid() |
if ppid == 1 { |
pid = Getpid() |
err2 := Kill(pid, sys.Pdeathsig) |
if err2 != nil { |
err1 = err2.(Errno) |
goto childerror |
} |
} |
} |
|
// Enable tracing if requested. |
if sys.Ptrace { |
err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil) |
if err1 != 0 { |
goto childerror |
} |
} |
|
// Session ID |
if sys.Setsid { |
err1 = raw_setsid() |
if err1 != 0 { |
goto childerror |
} |
} |
|
// Set process group |
if sys.Setpgid { |
err1 = raw_setpgid(0, 0) |
if err1 != 0 { |
goto childerror |
} |
} |
|
// Chroot |
if chroot != nil { |
err1 = raw_chroot(chroot) |
if err1 != 0 { |
goto childerror |
} |
} |
|
// User and groups |
if cred := sys.Credential; cred != nil { |
ngroups := len(cred.Groups) |
if ngroups == 0 { |
err2 := setgroups(0, nil) |
if err2 == nil { |
err1 = 0 |
} else { |
err1 = err2.(Errno) |
} |
} else { |
groups := make([]Gid_t, ngroups) |
for i, v := range cred.Groups { |
groups[i] = Gid_t(v) |
} |
err2 := setgroups(ngroups, &groups[0]) |
if err2 == nil { |
err1 = 0 |
} else { |
err1 = err2.(Errno) |
} |
} |
if err1 != 0 { |
goto childerror |
} |
err2 := Setgid(int(cred.Gid)) |
if err2 != nil { |
err1 = err2.(Errno) |
goto childerror |
} |
err2 = Setuid(int(cred.Uid)) |
if err2 != nil { |
err1 = err2.(Errno) |
goto childerror |
} |
} |
|
// Chdir |
if dir != nil { |
err1 = raw_chdir(dir) |
if err1 != 0 { |
goto childerror |
} |
} |
|
// Pass 1: look for fd[i] < i and move those up above len(fd) |
// so that pass 2 won't stomp on an fd it needs later. |
nextfd = int(len(fd)) |
if pipe < nextfd { |
err1 = raw_dup2(pipe, nextfd) |
if err1 != 0 { |
goto childerror |
} |
raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC) |
pipe = nextfd |
nextfd++ |
} |
for i = 0; i < len(fd); i++ { |
if fd[i] >= 0 && fd[i] < int(i) { |
err1 = raw_dup2(fd[i], nextfd) |
if err1 != 0 { |
goto childerror |
} |
raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC) |
fd[i] = nextfd |
nextfd++ |
if nextfd == pipe { // don't stomp on pipe |
nextfd++ |
} |
} |
} |
|
// Pass 2: dup fd[i] down onto i. |
for i = 0; i < len(fd); i++ { |
if fd[i] == -1 { |
raw_close(i) |
continue |
} |
if fd[i] == int(i) { |
// dup2(i, i) won't clear close-on-exec flag on Linux, |
// probably not elsewhere either. |
_, err1 = raw_fcntl(fd[i], F_SETFD, 0) |
if err1 != 0 { |
goto childerror |
} |
continue |
} |
// The new fd is created NOT close-on-exec, |
// which is exactly what we want. |
err1 = raw_dup2(fd[i], i) |
if err1 != 0 { |
goto childerror |
} |
} |
|
// By convention, we don't close-on-exec the fds we are |
// started with, so if len(fd) < 3, close 0, 1, 2 as needed. |
// Programs that know they inherit fds >= 3 will need |
// to set them close-on-exec. |
for i = len(fd); i < 3; i++ { |
raw_close(i) |
} |
|
// Detach fd 0 from tty |
if sys.Noctty { |
_, err1 = raw_ioctl(0, TIOCNOTTY, 0) |
if err1 != 0 { |
goto childerror |
} |
} |
|
// Make fd 0 the tty |
if sys.Setctty { |
_, err1 = raw_ioctl(0, TIOCSCTTY, 0) |
if err1 != 0 { |
goto childerror |
} |
} |
|
// Time to exec. |
err1 = raw_execve(argv0, &argv[0], &envv[0]) |
|
childerror: |
// send error code on pipe |
raw_write(pipe, (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1))) |
for { |
raw_exit(253) |
} |
|
// Calling panic is not actually safe, |
// but the for loop above won't break |
// and this shuts up the compiler. |
panic("unreached") |
} |
/lsf_linux.go
0,0 → 1,78
// Copyright 2011 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// Linux socket filter |
|
package syscall |
|
import ( |
"unsafe" |
) |
|
func LsfStmt(code, k int) *SockFilter { |
return &SockFilter{Code: uint16(code), K: uint32(k)} |
} |
|
func LsfJump(code, k, jt, jf int) *SockFilter { |
return &SockFilter{Code: uint16(code), Jt: uint8(jt), Jf: uint8(jf), K: uint32(k)} |
} |
|
func LsfSocket(ifindex, proto int) (int, error) { |
var lsall SockaddrLinklayer |
s, e := Socket(AF_PACKET, SOCK_RAW, proto) |
if e != nil { |
return 0, e |
} |
p := (*[2]byte)(unsafe.Pointer(&lsall.Protocol)) |
p[0] = byte(proto >> 8) |
p[1] = byte(proto) |
lsall.Ifindex = ifindex |
e = Bind(s, &lsall) |
if e != nil { |
Close(s) |
return 0, e |
} |
return s, nil |
} |
|
type iflags struct { |
name [IFNAMSIZ]byte |
flags uint16 |
} |
|
func SetLsfPromisc(name string, m bool) error { |
s, e := Socket(AF_INET, SOCK_DGRAM, 0) |
if e != nil { |
return e |
} |
defer Close(s) |
var ifl iflags |
copy(ifl.name[:], []byte(name)) |
_, _, ep := Syscall(SYS_IOCTL, uintptr(s), SIOCGIFFLAGS, uintptr(unsafe.Pointer(&ifl))) |
if ep != 0 { |
return Errno(ep) |
} |
if m { |
ifl.flags |= uint16(IFF_PROMISC) |
} else { |
ifl.flags &= ^uint16(IFF_PROMISC) |
} |
_, _, ep = Syscall(SYS_IOCTL, uintptr(s), SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifl))) |
if ep != 0 { |
return Errno(ep) |
} |
return nil |
} |
|
func AttachLsf(fd int, i []SockFilter) error { |
var p SockFprog |
p.Len = uint16(len(i)) |
p.Filter = (*SockFilter)(unsafe.Pointer(&i[0])) |
return setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, uintptr(unsafe.Pointer(&p)), unsafe.Sizeof(p)) |
} |
|
func DetachLsf(fd int) error { |
var dummy int |
return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, uintptr(unsafe.Pointer(&dummy)), unsafe.Sizeof(dummy)) |
} |
/socket_linux.go
0,0 → 1,177
// socket_linux.go -- Socket handling specific to GNU/Linux. |
|
// Copyright 2010 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
package syscall |
|
import "unsafe" |
|
const SizeofSockaddrInet4 = 16 |
const SizeofSockaddrInet6 = 28 |
const SizeofSockaddrUnix = 110 |
const SizeofSockaddrLinklayer = 20 |
const SizeofSockaddrNetlink = 12 |
|
type SockaddrLinklayer struct { |
Protocol uint16 |
Ifindex int |
Hatype uint16 |
Pkttype uint8 |
Halen uint8 |
Addr [8]byte |
raw RawSockaddrLinklayer |
} |
|
func (sa *SockaddrLinklayer) sockaddr() (*RawSockaddrAny, Socklen_t, error) { |
if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff { |
return nil, 0, EINVAL |
} |
sa.raw.Family = AF_PACKET |
sa.raw.Protocol = sa.Protocol |
sa.raw.Ifindex = int32(sa.Ifindex) |
sa.raw.Hatype = sa.Hatype |
sa.raw.Pkttype = sa.Pkttype |
sa.raw.Halen = sa.Halen |
for i := 0; i < len(sa.Addr); i++ { |
sa.raw.Addr[i] = sa.Addr[i] |
} |
return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrLinklayer, nil |
} |
|
type SockaddrNetlink struct { |
Family uint16 |
Pad uint16 |
Pid uint32 |
Groups uint32 |
raw RawSockaddrNetlink |
} |
|
func (sa *SockaddrNetlink) sockaddr() (*RawSockaddrAny, Socklen_t, error) { |
sa.raw.Family = AF_NETLINK |
sa.raw.Pad = sa.Pad |
sa.raw.Pid = sa.Pid |
sa.raw.Groups = sa.Groups |
return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrNetlink, nil |
} |
|
type RawSockaddrInet4 struct { |
Family uint16 |
Port uint16 |
Addr [4]byte /* in_addr */ |
Zero [8]uint8 |
} |
|
func (sa *RawSockaddrInet4) setLen() Socklen_t { |
return SizeofSockaddrInet4 |
} |
|
type RawSockaddrInet6 struct { |
Family uint16 |
Port uint16 |
Flowinfo uint32 |
Addr [16]byte /* in6_addr */ |
Scope_id uint32 |
} |
|
func (sa *RawSockaddrInet6) setLen() Socklen_t { |
return SizeofSockaddrInet6 |
} |
|
type RawSockaddrUnix struct { |
Family uint16 |
Path [108]int8 |
} |
|
func (sa *RawSockaddrUnix) setLen(int) { |
} |
|
func (sa *RawSockaddrUnix) getLen() (int, error) { |
if sa.Path[0] == 0 { |
// "Abstract" Unix domain socket. |
// Rewrite leading NUL as @ for textual display. |
// (This is the standard convention.) |
// Not friendly to overwrite in place, |
// but the callers below don't care. |
sa.Path[0] = '@' |
} |
|
// Assume path ends at NUL. |
// This is not technically the GNU/Linux semantics for |
// abstract Unix domain sockets--they are supposed |
// to be uninterpreted fixed-size binary blobs--but |
// everyone uses this convention. |
n := 0 |
for n < len(sa.Path) - 3 && sa.Path[n] != 0 { |
n++ |
} |
|
return n, nil |
} |
|
type RawSockaddrLinklayer struct { |
Family uint16 |
Protocol uint16 |
Ifindex int32 |
Hatype uint16 |
Pkttype uint8 |
Halen uint8 |
Addr [8]uint8 |
} |
|
type RawSockaddrNetlink struct { |
Family uint16 |
Pad uint16 |
Pid uint32 |
Groups uint32 |
} |
|
type RawSockaddr struct { |
Family uint16 |
Data [14]int8 |
} |
|
// BindToDevice binds the socket associated with fd to device. |
func BindToDevice(fd int, device string) (err error) { |
return SetsockoptString(fd, SOL_SOCKET, SO_BINDTODEVICE, device) |
} |
|
func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, error) { |
switch rsa.Addr.Family { |
case AF_NETLINK: |
pp := (*RawSockaddrNetlink)(unsafe.Pointer(rsa)) |
sa := new(SockaddrNetlink) |
sa.Family = pp.Family |
sa.Pad = pp.Pad |
sa.Pid = pp.Pid |
sa.Groups = pp.Groups |
return sa, nil |
|
case AF_PACKET: |
pp := (*RawSockaddrLinklayer)(unsafe.Pointer(rsa)) |
sa := new(SockaddrLinklayer) |
sa.Protocol = pp.Protocol |
sa.Ifindex = int(pp.Ifindex) |
sa.Hatype = pp.Hatype |
sa.Pkttype = pp.Pkttype |
sa.Halen = pp.Halen |
for i := 0; i < len(sa.Addr); i++ { |
sa.Addr[i] = pp.Addr[i] |
} |
return sa, nil |
} |
return nil, EAFNOSUPPORT |
} |
|
//sysnb EpollCreate(size int) (fd int, err error) |
//epoll_create(size int) int |
|
//sysnb EpollCreate1(flags int) (fd int, err error) |
//epoll_create1(flags int) int |
|
//sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) |
//epoll_ctl(epfd int, op int, fd int, event *EpollEvent) int |
|
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) |
//epoll_wait(epfd int, events *EpollEvent, maxevents int, timeout int) int |
/syscall.go
0,0 → 1,53
// Copyright 2009 The Go Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style |
// license that can be found in the LICENSE file. |
|
// Package syscall contains an interface to the low-level operating system |
// primitives. The details vary depending on the underlying system. |
// Its primary use is inside other packages that provide a more portable |
// interface to the system, such as "os", "time" and "net". Use those |
// packages rather than this one if you can. |
// For details of the functions and data types in this package consult |
// the manuals for the appropriate operating system. |
// These calls return err == nil to indicate success; otherwise |
// err is an operating system error describing the failure. |
// On most systems, that error has type syscall.Errno. |
package syscall |
|
import "unsafe" |
|
// StringByteSlice returns a NUL-terminated slice of bytes |
// containing the text of s. |
func StringByteSlice(s string) []byte { |
a := make([]byte, len(s)+1) |
copy(a, s) |
return a |
} |
|
// StringBytePtr returns a pointer to a NUL-terminated array of bytes |
// containing the text of s. |
func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] } |
|
// Single-word zero for use when we need a valid pointer to 0 bytes. |
// See mksyscall.pl. |
var _zero uintptr |
|
var dummy *byte |
|
const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy)) |
|
func (ts *Timespec) Unix() (sec int64, nsec int64) { |
return int64(ts.Sec), int64(ts.Nsec) |
} |
|
func (tv *Timeval) Unix() (sec int64, nsec int64) { |
return int64(tv.Sec), int64(tv.Usec) * 1000 |
} |
|
func (ts *Timespec) Nano() int64 { |
return int64(ts.Sec)*1e9 + int64(ts.Nsec) |
} |
|
func (tv *Timeval) Nano() int64 { |
return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000 |
} |