mirror of
https://github.com/golang/go.git
synced 2024-10-01 07:17:21 +00:00
R=rsc, brainman, ality, r2, r
CC=golang-dev https://golang.org/cl/3816043
This commit is contained in:
parent
c42b3e21c3
commit
1cc4a5cd94
@ -33,6 +33,9 @@ GOFILES_linux=\
|
|||||||
GOFILES_windows=\
|
GOFILES_windows=\
|
||||||
exec_windows.go
|
exec_windows.go
|
||||||
|
|
||||||
|
GOFILES_plan9=\
|
||||||
|
exec_plan9.go
|
||||||
|
|
||||||
OFILES=\
|
OFILES=\
|
||||||
asm_$(GOOS)_$(GOARCH).$O\
|
asm_$(GOOS)_$(GOARCH).$O\
|
||||||
|
|
||||||
|
151
src/pkg/syscall/asm_plan9_386.s
Normal file
151
src/pkg/syscall/asm_plan9_386.s
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
//
|
||||||
|
// System call support for 386, Plan 9
|
||||||
|
//
|
||||||
|
|
||||||
|
//func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err string)
|
||||||
|
//func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err string)
|
||||||
|
//func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
|
||||||
|
//func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
|
||||||
|
|
||||||
|
// Trap # in AX, args on stack above caller pc.
|
||||||
|
TEXT ·Syscall(SB),7,$0
|
||||||
|
CALL runtime·entersyscall(SB)
|
||||||
|
MOVL 4(SP), AX // syscall entry
|
||||||
|
// slide args down on top of system call number
|
||||||
|
LEAL 8(SP), SI
|
||||||
|
LEAL 4(SP), DI
|
||||||
|
CLD
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
INT $64
|
||||||
|
MOVL AX, r1+20(SP)
|
||||||
|
MOVL $0, r2+24(SP)
|
||||||
|
CMPL AX, $-1
|
||||||
|
JNE ok3
|
||||||
|
|
||||||
|
SUBL $8, SP
|
||||||
|
CALL syscall·errstr(SB)
|
||||||
|
MOVL SP, SI
|
||||||
|
ADDL $8, SP
|
||||||
|
JMP copyresult3
|
||||||
|
|
||||||
|
ok3:
|
||||||
|
LEAL runtime·emptystring(SB), SI
|
||||||
|
|
||||||
|
copyresult3:
|
||||||
|
LEAL err+28(SP), DI
|
||||||
|
|
||||||
|
CLD
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
|
||||||
|
CALL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),7,$0
|
||||||
|
CALL runtime·entersyscall(SB)
|
||||||
|
MOVL 4(SP), AX // syscall entry
|
||||||
|
// slide args down on top of system call number
|
||||||
|
LEAL 8(SP), SI
|
||||||
|
LEAL 4(SP), DI
|
||||||
|
CLD
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
INT $64
|
||||||
|
MOVL AX, r1+32(SP)
|
||||||
|
MOVL $0, r2+36(SP)
|
||||||
|
CMPL AX, $-1
|
||||||
|
JNE ok4
|
||||||
|
|
||||||
|
SUBL $8, SP
|
||||||
|
CALL syscall·errstr(SB)
|
||||||
|
MOVL SP, SI
|
||||||
|
ADDL $8, SP
|
||||||
|
JMP copyresult4
|
||||||
|
|
||||||
|
ok4:
|
||||||
|
LEAL runtime·emptystring(SB), SI
|
||||||
|
|
||||||
|
copyresult4:
|
||||||
|
LEAL err+40(SP), DI
|
||||||
|
|
||||||
|
CLD
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
|
||||||
|
CALL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),7,$0
|
||||||
|
MOVL 4(SP), AX // syscall entry
|
||||||
|
// slide args down on top of system call number
|
||||||
|
LEAL 8(SP), SI
|
||||||
|
LEAL 4(SP), DI
|
||||||
|
CLD
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
INT $64
|
||||||
|
MOVL AX, r1+20(SP)
|
||||||
|
MOVL AX, r2+24(SP)
|
||||||
|
MOVL AX, err+28(SP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),7,$0
|
||||||
|
MOVL 4(SP), AX // syscall entry
|
||||||
|
// slide args down on top of system call number
|
||||||
|
LEAL 8(SP), SI
|
||||||
|
LEAL 4(SP), DI
|
||||||
|
CLD
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
INT $64
|
||||||
|
MOVL AX, r1+32(SP)
|
||||||
|
MOVL AX, r2+36(SP)
|
||||||
|
MOVL AX, err+40(SP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
#define SYS_SEEK 39 /* from zsysnum_plan9_386.go */
|
||||||
|
|
||||||
|
//func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
|
||||||
|
TEXT ·seek(SB),7,$0
|
||||||
|
LEAL newoffset+24(SP), AX
|
||||||
|
MOVL AX, placeholder+4(SP)
|
||||||
|
|
||||||
|
MOVL $SYS_SEEK, AX // syscall entry
|
||||||
|
INT $64
|
||||||
|
|
||||||
|
CMPL AX, $-1
|
||||||
|
JNE ok6
|
||||||
|
MOVL AX, 24(SP) // newoffset low
|
||||||
|
MOVL AX, 28(SP) // newoffset high
|
||||||
|
|
||||||
|
SUBL $8, SP
|
||||||
|
CALL syscall·errstr(SB)
|
||||||
|
MOVL SP, SI
|
||||||
|
ADDL $8, SP
|
||||||
|
JMP copyresult6
|
||||||
|
|
||||||
|
ok6:
|
||||||
|
LEAL runtime·emptystring(SB), SI
|
||||||
|
|
||||||
|
copyresult6:
|
||||||
|
LEAL err+32(SP), DI
|
||||||
|
|
||||||
|
CLD
|
||||||
|
MOVSL
|
||||||
|
MOVSL
|
||||||
|
RET
|
521
src/pkg/syscall/exec_plan9.go
Normal file
521
src/pkg/syscall/exec_plan9.go
Normal file
@ -0,0 +1,521 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Fork, exec, wait, etc.
|
||||||
|
|
||||||
|
package syscall
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Lock synchronizing creation of new file descriptors with fork.
|
||||||
|
//
|
||||||
|
// We want the child in a fork/exec sequence to inherit only the
|
||||||
|
// file descriptors we intend. To do that, we mark all file
|
||||||
|
// descriptors close-on-exec and then, in the child, explicitly
|
||||||
|
// unmark the ones we want the exec'ed program to keep.
|
||||||
|
// Unix doesn't make this easy: there is, in general, no way to
|
||||||
|
// allocate a new file descriptor close-on-exec. Instead you
|
||||||
|
// have to allocate the descriptor and then mark it close-on-exec.
|
||||||
|
// If a fork happens between those two events, the child's exec
|
||||||
|
// will inherit an unwanted file descriptor.
|
||||||
|
//
|
||||||
|
// This lock solves that race: the create new fd/mark close-on-exec
|
||||||
|
// operation is done holding ForkLock for reading, and the fork itself
|
||||||
|
// is done holding ForkLock for writing. At least, that's the idea.
|
||||||
|
// There are some complications.
|
||||||
|
//
|
||||||
|
// Some system calls that create new file descriptors can block
|
||||||
|
// for arbitrarily long times: open on a hung NFS server or named
|
||||||
|
// pipe, accept on a socket, and so on. We can't reasonably grab
|
||||||
|
// the lock across those operations.
|
||||||
|
//
|
||||||
|
// It is worse to inherit some file descriptors than others.
|
||||||
|
// If a non-malicious child accidentally inherits an open ordinary file,
|
||||||
|
// that's not a big deal. On the other hand, if a long-lived child
|
||||||
|
// accidentally inherits the write end of a pipe, then the reader
|
||||||
|
// of that pipe will not see EOF until that child exits, potentially
|
||||||
|
// causing the parent program to hang. This is a common problem
|
||||||
|
// in threaded C programs that use popen.
|
||||||
|
//
|
||||||
|
// Luckily, the file descriptors that are most important not to
|
||||||
|
// inherit are not the ones that can take an arbitrarily long time
|
||||||
|
// to create: pipe returns instantly, and the net package uses
|
||||||
|
// non-blocking I/O to accept on a listening socket.
|
||||||
|
// The rules for which file descriptor-creating operations use the
|
||||||
|
// ForkLock are as follows:
|
||||||
|
//
|
||||||
|
// 1) Pipe. Does not block. Use the ForkLock.
|
||||||
|
// 2) Socket. Does not block. Use the ForkLock.
|
||||||
|
// 3) Accept. If using non-blocking mode, use the ForkLock.
|
||||||
|
// Otherwise, live with the race.
|
||||||
|
// 4) Open. Can block. Use O_CLOEXEC if available (Linux).
|
||||||
|
// Otherwise, live with the race.
|
||||||
|
// 5) Dup. Does not block. Use the ForkLock.
|
||||||
|
// On Linux, could use fcntl F_DUPFD_CLOEXEC
|
||||||
|
// instead of the ForkLock, but only for dup(fd, -1).
|
||||||
|
|
||||||
|
var ForkLock sync.RWMutex
|
||||||
|
|
||||||
|
// Convert array of string to array
|
||||||
|
// of NUL-terminated byte pointer.
|
||||||
|
func StringArrayPtr(ss []string) []*byte {
|
||||||
|
bb := make([]*byte, len(ss)+1)
|
||||||
|
for i := 0; i < len(ss); i++ {
|
||||||
|
bb[i] = StringBytePtr(ss[i])
|
||||||
|
}
|
||||||
|
bb[len(ss)] = nil
|
||||||
|
return bb
|
||||||
|
}
|
||||||
|
|
||||||
|
// gbit16 reads a 16-bit numeric value from a 9P protocol message strored in b,
|
||||||
|
// returning the value and the remaining slice of b.
|
||||||
|
func gbit16(b []byte) (uint16, []byte) {
|
||||||
|
return uint16(b[0]) | uint16(b[1])<<8, b[2:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// gstring reads a string from a 9P protocol message strored in b,
|
||||||
|
// returning the value as a Go string and the remaining slice of b.
|
||||||
|
func gstring(b []byte) (string, []byte) {
|
||||||
|
n, b := gbit16(b)
|
||||||
|
return string(b[0:n]), b[n:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// readdirnames returns the names of files inside the directory represented by dirfd.
|
||||||
|
func readdirnames(dirfd int) (names []string, err Error) {
|
||||||
|
result := make([]string, 0, 100)
|
||||||
|
var buf [STATMAX]byte
|
||||||
|
|
||||||
|
for {
|
||||||
|
n, e := Read(dirfd, buf[:])
|
||||||
|
if e != nil {
|
||||||
|
return []string{}, e
|
||||||
|
}
|
||||||
|
if n == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < n; {
|
||||||
|
m, _ := gbit16(buf[i:])
|
||||||
|
m += 2
|
||||||
|
|
||||||
|
if m < STATFIXLEN {
|
||||||
|
return []string{}, NewError("malformed stat buffer")
|
||||||
|
}
|
||||||
|
|
||||||
|
name, _ := gstring(buf[i+41:])
|
||||||
|
result = append(result, name)
|
||||||
|
|
||||||
|
i += int(m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return []string{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// readdupdevice returns a list of currently opened fds (excluding stdin, stdout, stderr) from the dup device #d.
|
||||||
|
// ForkLock should be write locked before calling, so that no new fds would be created while the fd list is being read.
|
||||||
|
func readdupdevice() (fds []int, err Error) {
|
||||||
|
dupdevfd, err := Open("#d", O_RDONLY)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer Close(dupdevfd)
|
||||||
|
|
||||||
|
fileNames, err := readdirnames(dupdevfd)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fds = make([]int, 0, len(fileNames)>>1)
|
||||||
|
for _, fdstr := range fileNames {
|
||||||
|
if l := len(fdstr); l > 2 && fdstr[l-3] == 'c' && fdstr[l-2] == 't' && fdstr[l-1] == 'l' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fd := int(atoi([]byte(fdstr)))
|
||||||
|
|
||||||
|
if fd == 0 || fd == 1 || fd == 2 || fd == dupdevfd {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fds = append(fds, fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fds[0:len(fds)], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var startupFds []int
|
||||||
|
|
||||||
|
// Plan 9 does not allow clearing the OCEXEC flag
|
||||||
|
// from the underlying channel backing an open file descriptor,
|
||||||
|
// therefore we store a list of already opened file descriptors
|
||||||
|
// inside startupFds and skip them when manually closing descriptors
|
||||||
|
// not meant to be passed to a child exec.
|
||||||
|
func init() {
|
||||||
|
startupFds, _ = readdupdevice()
|
||||||
|
}
|
||||||
|
|
||||||
|
// forkAndExecInChild forks the process, calling dup onto 0..len(fd)
|
||||||
|
// and finally invoking exec(argv0, argvv, envv) in the child.
|
||||||
|
// If a dup or exec fails, it writes the error string to pipe.
|
||||||
|
// (The pipe write end is close-on-exec so if exec succeeds, it will be closed.)
|
||||||
|
//
|
||||||
|
// In the child, this function must not acquire any locks, because
|
||||||
|
// they might have been locked at the time of the fork. This means
|
||||||
|
// no rescheduling, no malloc calls, and no new stack segments.
|
||||||
|
// The calls to RawSyscall are okay because they are assembly
|
||||||
|
// functions that do not grow the stack.
|
||||||
|
func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, chroot, dir *byte, attr *ProcAttr, fdsToClose []int, pipe int) (pid int, err Error) {
|
||||||
|
// Declare all variables at top in case any
|
||||||
|
// declarations require heap allocation (e.g., errbuf).
|
||||||
|
var (
|
||||||
|
r1 uintptr
|
||||||
|
nextfd int
|
||||||
|
i int
|
||||||
|
clearenv int
|
||||||
|
envfd int
|
||||||
|
errbuf [ERRMAX]byte
|
||||||
|
)
|
||||||
|
|
||||||
|
// guard against side effects of shuffling fds below.
|
||||||
|
fd := append([]int(nil), attr.Files...)
|
||||||
|
|
||||||
|
if envv != nil {
|
||||||
|
clearenv = RFCENVG
|
||||||
|
}
|
||||||
|
|
||||||
|
// About to call fork.
|
||||||
|
// No more allocation or calls of non-assembly functions.
|
||||||
|
r1, _, _ = RawSyscall(SYS_RFORK, uintptr(RFPROC|RFFDG|RFREND|clearenv), 0, 0)
|
||||||
|
|
||||||
|
if r1 != 0 {
|
||||||
|
if int(r1) == -1 {
|
||||||
|
return 0, NewError(errstr())
|
||||||
|
}
|
||||||
|
// parent; return PID
|
||||||
|
return int(r1), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fork succeeded, now in child.
|
||||||
|
|
||||||
|
// Close fds we don't need.
|
||||||
|
for i = 0; i < len(fdsToClose); i++ {
|
||||||
|
r1, _, _ = RawSyscall(SYS_CLOSE, uintptr(fdsToClose[i]), 0, 0)
|
||||||
|
if int(r1) == -1 {
|
||||||
|
goto childerror
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if envv != nil {
|
||||||
|
// Write new environment variables.
|
||||||
|
for i = 0; i < len(envv); i++ {
|
||||||
|
r1, _, _ = RawSyscall(SYS_CREATE, uintptr(unsafe.Pointer(envv[i].name)), uintptr(O_WRONLY), uintptr(0666))
|
||||||
|
|
||||||
|
if int(r1) == -1 {
|
||||||
|
goto childerror
|
||||||
|
}
|
||||||
|
|
||||||
|
envfd = int(r1)
|
||||||
|
|
||||||
|
r1, _, _ = RawSyscall6(SYS_PWRITE, uintptr(envfd), uintptr(unsafe.Pointer(envv[i].value)), uintptr(envv[i].nvalue),
|
||||||
|
^uintptr(0), ^uintptr(0), 0)
|
||||||
|
|
||||||
|
if int(r1) == -1 || int(r1) != envv[i].nvalue {
|
||||||
|
goto childerror
|
||||||
|
}
|
||||||
|
|
||||||
|
r1, _, _ = RawSyscall(SYS_CLOSE, uintptr(envfd), 0, 0)
|
||||||
|
|
||||||
|
if int(r1) == -1 {
|
||||||
|
goto childerror
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chdir
|
||||||
|
if dir != nil {
|
||||||
|
r1, _, _ = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0)
|
||||||
|
if int(r1) == -1 {
|
||||||
|
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 {
|
||||||
|
r1, _, _ = RawSyscall(SYS_DUP, uintptr(pipe), uintptr(nextfd), 0)
|
||||||
|
if int(r1) == -1 {
|
||||||
|
goto childerror
|
||||||
|
}
|
||||||
|
pipe = nextfd
|
||||||
|
nextfd++
|
||||||
|
}
|
||||||
|
for i = 0; i < len(fd); i++ {
|
||||||
|
if fd[i] >= 0 && fd[i] < int(i) {
|
||||||
|
r1, _, _ = RawSyscall(SYS_DUP, uintptr(fd[i]), uintptr(nextfd), 0)
|
||||||
|
if int(r1) == -1 {
|
||||||
|
goto childerror
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if fd[i] == int(i) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r1, _, _ = RawSyscall(SYS_DUP, uintptr(fd[i]), uintptr(i), 0)
|
||||||
|
if int(r1) == -1 {
|
||||||
|
goto childerror
|
||||||
|
}
|
||||||
|
RawSyscall(SYS_CLOSE, uintptr(fd[i]), 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time to exec.
|
||||||
|
r1, _, _ = RawSyscall(SYS_EXEC,
|
||||||
|
uintptr(unsafe.Pointer(argv0)),
|
||||||
|
uintptr(unsafe.Pointer(&argv[0])), 0)
|
||||||
|
|
||||||
|
childerror:
|
||||||
|
// send error string on pipe
|
||||||
|
RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&errbuf[0])), uintptr(len(errbuf)), 0)
|
||||||
|
errbuf[len(errbuf)-1] = 0
|
||||||
|
i = 0
|
||||||
|
for i < len(errbuf) && errbuf[i] != 0 {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
RawSyscall6(SYS_PWRITE, uintptr(pipe), uintptr(unsafe.Pointer(&errbuf[0])), uintptr(i),
|
||||||
|
^uintptr(0), ^uintptr(0), 0)
|
||||||
|
|
||||||
|
for {
|
||||||
|
RawSyscall(SYS_EXITS, 0, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calling panic is not actually safe,
|
||||||
|
// but the for loop above won't break
|
||||||
|
// and this shuts up the compiler.
|
||||||
|
panic("unreached")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cexecPipe(p []int) Error {
|
||||||
|
e := Pipe(p)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
fd, e := Open("#d/"+itoa(p[1]), O_CLOEXEC)
|
||||||
|
if e != nil {
|
||||||
|
Close(p[0])
|
||||||
|
Close(p[1])
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
Close(fd)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type envItem struct {
|
||||||
|
name *byte
|
||||||
|
value *byte
|
||||||
|
nvalue int
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProcAttr struct {
|
||||||
|
Dir string // Current working directory.
|
||||||
|
Env []string // Environment.
|
||||||
|
Files []int // File descriptors.
|
||||||
|
Chroot string // Chroot.
|
||||||
|
}
|
||||||
|
|
||||||
|
var zeroAttributes ProcAttr
|
||||||
|
|
||||||
|
|
||||||
|
func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err Error) {
|
||||||
|
var (
|
||||||
|
p [2]int
|
||||||
|
n int
|
||||||
|
errbuf [ERRMAX]byte
|
||||||
|
wmsg Waitmsg
|
||||||
|
)
|
||||||
|
|
||||||
|
if attr == nil {
|
||||||
|
attr = &zeroAttributes
|
||||||
|
}
|
||||||
|
|
||||||
|
p[0] = -1
|
||||||
|
p[1] = -1
|
||||||
|
|
||||||
|
// Convert args to C form.
|
||||||
|
argv0p := StringBytePtr(argv[0])
|
||||||
|
argvp := StringArrayPtr(argv)
|
||||||
|
|
||||||
|
var chroot *byte
|
||||||
|
if attr.Chroot != "" {
|
||||||
|
chroot = StringBytePtr(attr.Chroot)
|
||||||
|
}
|
||||||
|
var dir *byte
|
||||||
|
if attr.Dir != "" {
|
||||||
|
dir = StringBytePtr(attr.Dir)
|
||||||
|
}
|
||||||
|
var envvParsed []envItem
|
||||||
|
if attr.Env != nil {
|
||||||
|
envvParsed = make([]envItem, 0, len(attr.Env))
|
||||||
|
for _, v := range attr.Env {
|
||||||
|
i := 0
|
||||||
|
for i < len(v) && v[i] != '=' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
envvParsed = append(envvParsed, envItem{StringBytePtr("/env/" + v[:i]), StringBytePtr(v[i+1:]), len(v) - i})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Acquire the fork lock to prevent other threads from creating new fds before we fork.
|
||||||
|
ForkLock.Lock()
|
||||||
|
|
||||||
|
// get a list of open fds, excluding stdin,stdout and stderr that need to be closed in the child.
|
||||||
|
// no new fds can be created while we hold the ForkLock for writing.
|
||||||
|
openFds, e := readdupdevice()
|
||||||
|
|
||||||
|
if e != nil {
|
||||||
|
ForkLock.Unlock()
|
||||||
|
return 0, e
|
||||||
|
}
|
||||||
|
|
||||||
|
fdsToClose := make([]int, 0, len(openFds))
|
||||||
|
// exclude fds opened from startup from the list of fds to be closed.
|
||||||
|
for _, fd := range openFds {
|
||||||
|
isReserved := false
|
||||||
|
for _, reservedFd := range startupFds {
|
||||||
|
if fd == reservedFd {
|
||||||
|
isReserved = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isReserved {
|
||||||
|
fdsToClose = append(fdsToClose, fd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// exclude fds requested by the caller from the list of fds to be closed.
|
||||||
|
for _, fd := range openFds {
|
||||||
|
isReserved := false
|
||||||
|
for _, reservedFd := range attr.Files {
|
||||||
|
if fd == reservedFd {
|
||||||
|
isReserved = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isReserved {
|
||||||
|
fdsToClose = append(fdsToClose, fd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate child status pipe close on exec.
|
||||||
|
e = cexecPipe(p[:])
|
||||||
|
|
||||||
|
if e != nil {
|
||||||
|
return 0, e
|
||||||
|
}
|
||||||
|
fdsToClose = append(fdsToClose, p[0])
|
||||||
|
|
||||||
|
// Kick off child.
|
||||||
|
pid, err = forkAndExecInChild(argv0p, argvp, envvParsed, chroot, dir, attr, fdsToClose, p[1])
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if p[0] >= 0 {
|
||||||
|
Close(p[0])
|
||||||
|
Close(p[1])
|
||||||
|
}
|
||||||
|
ForkLock.Unlock()
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
ForkLock.Unlock()
|
||||||
|
|
||||||
|
// Read child error status from pipe.
|
||||||
|
Close(p[1])
|
||||||
|
n, err = Read(p[0], errbuf[:])
|
||||||
|
Close(p[0])
|
||||||
|
|
||||||
|
if err != nil || n != 0 {
|
||||||
|
if n != 0 {
|
||||||
|
err = NewError(string(errbuf[:]))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Child failed; wait for it to exit, to make sure
|
||||||
|
// the zombies don't accumulate.
|
||||||
|
for wmsg.Pid != pid {
|
||||||
|
Await(&wmsg)
|
||||||
|
}
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read got EOF, so pipe closed on exec, so exec succeeded.
|
||||||
|
return pid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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, handle int, err Error) {
|
||||||
|
pid, err = forkExec(argv0, argv, attr)
|
||||||
|
return pid, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ordinary exec.
|
||||||
|
func Exec(argv0 string, argv []string, envv []string) (err Error) {
|
||||||
|
if envv != nil {
|
||||||
|
r1, _, _ := RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
|
||||||
|
if int(r1) == -1 {
|
||||||
|
return NewError(errstr())
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range envv {
|
||||||
|
i := 0
|
||||||
|
for i < len(v) && v[i] != '=' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
fd, e := Create("/env/"+v[:i], O_WRONLY, 0666)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
_, e = Write(fd, []byte(v[i+1:]))
|
||||||
|
if e != nil {
|
||||||
|
Close(fd)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
Close(fd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, e := Syscall(SYS_EXEC,
|
||||||
|
uintptr(unsafe.Pointer(StringBytePtr(argv0))),
|
||||||
|
uintptr(unsafe.Pointer(&StringArrayPtr(argv)[0])),
|
||||||
|
0)
|
||||||
|
|
||||||
|
return NewError(e)
|
||||||
|
}
|
@ -145,6 +145,12 @@ windows_386)
|
|||||||
mktypes=
|
mktypes=
|
||||||
mkerrors="./mkerrors_windows.sh -f -m32"
|
mkerrors="./mkerrors_windows.sh -f -m32"
|
||||||
;;
|
;;
|
||||||
|
plan9_386)
|
||||||
|
mkerrors=
|
||||||
|
mksyscall="./mksyscall.pl -l32 -plan9"
|
||||||
|
mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
|
||||||
|
mktypes="godefs -gsyscall -f -m32"
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
|
echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -23,6 +23,7 @@ $cmdline = "mksyscall.pl " . join(' ', @ARGV);
|
|||||||
$errors = 0;
|
$errors = 0;
|
||||||
$_32bit = "";
|
$_32bit = "";
|
||||||
$nacl = 0;
|
$nacl = 0;
|
||||||
|
$plan9 = 0;
|
||||||
|
|
||||||
if($ARGV[0] eq "-b32") {
|
if($ARGV[0] eq "-b32") {
|
||||||
$_32bit = "big-endian";
|
$_32bit = "big-endian";
|
||||||
@ -35,6 +36,10 @@ if($ARGV[0] eq "-nacl") {
|
|||||||
$nacl = 1;
|
$nacl = 1;
|
||||||
shift;
|
shift;
|
||||||
}
|
}
|
||||||
|
if($ARGV[0] eq "-plan9") {
|
||||||
|
$plan9 = 1;
|
||||||
|
shift;
|
||||||
|
}
|
||||||
|
|
||||||
if($ARGV[0] =~ /^-/) {
|
if($ARGV[0] =~ /^-/) {
|
||||||
print STDERR "usage: mksyscall.pl [-b32 | -l32] [file ...]\n";
|
print STDERR "usage: mksyscall.pl [-b32 | -l32] [file ...]\n";
|
||||||
@ -160,9 +165,13 @@ while(<>) {
|
|||||||
my $p = $out[$i];
|
my $p = $out[$i];
|
||||||
my ($name, $type) = parseparam($p);
|
my ($name, $type) = parseparam($p);
|
||||||
my $reg = "";
|
my $reg = "";
|
||||||
if($name eq "errno") {
|
if($name eq "errno" && !$plan9) {
|
||||||
$reg = "e1";
|
$reg = "e1";
|
||||||
$ret[2] = $reg;
|
$ret[2] = $reg;
|
||||||
|
} elsif ($name eq "err" && $plan9) {
|
||||||
|
$ret[0] = "r0";
|
||||||
|
$ret[2] = "e1";
|
||||||
|
next;
|
||||||
} else {
|
} else {
|
||||||
$reg = sprintf("r%d", $i);
|
$reg = sprintf("r%d", $i);
|
||||||
$ret[$i] = $reg;
|
$ret[$i] = $reg;
|
||||||
@ -192,6 +201,13 @@ while(<>) {
|
|||||||
}
|
}
|
||||||
$text .= $body;
|
$text .= $body;
|
||||||
|
|
||||||
|
if ($plan9 && $ret[2] eq "e1") {
|
||||||
|
$text .= "\terr = nil\n";
|
||||||
|
$text .= "\tif int(r0) == -1 {\n";
|
||||||
|
$text .= "\t\t err = NewError(e1)\n";
|
||||||
|
$text .= "\t}\n";
|
||||||
|
}
|
||||||
|
|
||||||
$text .= "\treturn\n";
|
$text .= "\treturn\n";
|
||||||
$text .= "}\n\n";
|
$text .= "}\n\n";
|
||||||
}
|
}
|
||||||
|
25
src/pkg/syscall/mksysnum_plan9.sh
Executable file
25
src/pkg/syscall/mksysnum_plan9.sh
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style
|
||||||
|
# license that can be found in the LICENSE file.# 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.
|
||||||
|
|
||||||
|
COMMAND="mksysnum_plan9.sh $@"
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
// $COMMAND
|
||||||
|
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
|
||||||
|
|
||||||
|
package syscall
|
||||||
|
|
||||||
|
const(
|
||||||
|
EOF
|
||||||
|
|
||||||
|
SP='[ ]' # space or tab
|
||||||
|
sed "s/^#define${SP}\\([A-Z0-9_][A-Z0-9_]*\\)${SP}${SP}*\\([0-9][0-9]*\\)/SYS_\\1=\\2/g" \
|
||||||
|
< $1 | grep -v SYS__
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
)
|
||||||
|
EOF
|
@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
func str(val int) string { // do it here rather than with fmt to avoid dependency
|
func itoa(val int) string { // do it here rather than with fmt to avoid dependency
|
||||||
if val < 0 {
|
if val < 0 {
|
||||||
return "-" + str(-val)
|
return "-" + itoa(-val)
|
||||||
}
|
}
|
||||||
var buf [32]byte // big enough for int64
|
var buf [32]byte // big enough for int64
|
||||||
i := len(buf) - 1
|
i := len(buf) - 1
|
||||||
|
@ -60,7 +60,7 @@ func Futimesat(dirfd int, path string, tv []Timeval) (errno int) {
|
|||||||
func Futimes(fd int, tv []Timeval) (errno int) {
|
func Futimes(fd int, tv []Timeval) (errno int) {
|
||||||
// Believe it or not, this is the best we can do on Linux
|
// Believe it or not, this is the best we can do on Linux
|
||||||
// (and is what glibc does).
|
// (and is what glibc does).
|
||||||
return Utimes("/proc/self/fd/"+str(fd), tv)
|
return Utimes("/proc/self/fd/"+itoa(fd), tv)
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImplementsGetwd = true
|
const ImplementsGetwd = true
|
||||||
|
343
src/pkg/syscall/syscall_plan9.go
Normal file
343
src/pkg/syscall/syscall_plan9.go
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
// 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 system calls.
|
||||||
|
// This file is compiled as ordinary Go code,
|
||||||
|
// but it is also input to mksyscall,
|
||||||
|
// which parses the //sys lines and generates system call stubs.
|
||||||
|
// Note that sometimes we use a lowercase //sys name and
|
||||||
|
// wrap it in our own nicer implementation.
|
||||||
|
|
||||||
|
package syscall
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
const OS = "plan9"
|
||||||
|
|
||||||
|
const ImplementsGetwd = true
|
||||||
|
|
||||||
|
// An Error can represent any printable error condition.
|
||||||
|
type Error interface {
|
||||||
|
String() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorString implements Error's String method by returning itself.
|
||||||
|
type ErrorString string
|
||||||
|
|
||||||
|
func (e ErrorString) String() string { return string(e) }
|
||||||
|
|
||||||
|
// NewError converts s to an ErrorString, which satisfies the Error interface.
|
||||||
|
func NewError(s string) Error { return ErrorString(s) }
|
||||||
|
|
||||||
|
var (
|
||||||
|
Stdin = 0
|
||||||
|
Stdout = 1
|
||||||
|
Stderr = 2
|
||||||
|
|
||||||
|
EISDIR Error = NewError("file is a directory")
|
||||||
|
)
|
||||||
|
|
||||||
|
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err string)
|
||||||
|
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err string)
|
||||||
|
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
|
||||||
|
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
|
||||||
|
|
||||||
|
func atoi(b []byte) (n uint) {
|
||||||
|
n = 0
|
||||||
|
for i := 0; i < len(b); i++ {
|
||||||
|
n = n*10 + uint(b[i]-'0')
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func cstring(s []byte) string {
|
||||||
|
for i, _ := range s {
|
||||||
|
if s[i] == 0 {
|
||||||
|
return string(s[0:i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func errstr() string {
|
||||||
|
var buf [ERRMAX]byte
|
||||||
|
|
||||||
|
RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)
|
||||||
|
|
||||||
|
buf[len(buf)-1] = 0
|
||||||
|
return cstring(buf[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getpagesize() int { return 4096 }
|
||||||
|
|
||||||
|
//sys exits(msg *byte)
|
||||||
|
func Exits(msg *string) {
|
||||||
|
if msg == nil {
|
||||||
|
exits(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
exits(StringBytePtr(*msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Exit(code int) {
|
||||||
|
if code == 0 {
|
||||||
|
Exits(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := itoa(code)
|
||||||
|
Exits(&msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func readnum(path string) (uint, Error) {
|
||||||
|
var b [12]byte
|
||||||
|
|
||||||
|
fd, e := Open(path, O_RDONLY)
|
||||||
|
if e != nil {
|
||||||
|
return 0, e
|
||||||
|
}
|
||||||
|
defer Close(fd)
|
||||||
|
|
||||||
|
n, e := Pread(fd, b[:], 0)
|
||||||
|
|
||||||
|
if e != nil {
|
||||||
|
return 0, e
|
||||||
|
}
|
||||||
|
|
||||||
|
m := 0
|
||||||
|
for ; m < n && b[m] == ' '; m++ {
|
||||||
|
}
|
||||||
|
|
||||||
|
return atoi(b[m : n-1]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getpid() (pid int) {
|
||||||
|
n, _ := readnum("#c/pid")
|
||||||
|
return int(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getppid() (ppid int) {
|
||||||
|
n, _ := readnum("#c/ppid")
|
||||||
|
return int(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func Read(fd int, p []byte) (n int, err Error) {
|
||||||
|
return Pread(fd, p, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Write(fd int, p []byte) (n int, err Error) {
|
||||||
|
return Pwrite(fd, p, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getwd() (wd string, err Error) {
|
||||||
|
fd, e := Open(".", O_RDONLY)
|
||||||
|
|
||||||
|
if e != nil {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
defer Close(fd)
|
||||||
|
|
||||||
|
return Fd2path(fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys fd2path(fd int, buf []byte) (err Error)
|
||||||
|
func Fd2path(fd int) (path string, err Error) {
|
||||||
|
var buf [512]byte
|
||||||
|
|
||||||
|
e := fd2path(fd, buf[:])
|
||||||
|
if e != nil {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
return cstring(buf[:]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys pipe(p *[2]_C_int) (err Error)
|
||||||
|
func Pipe(p []int) (err Error) {
|
||||||
|
if len(p) != 2 {
|
||||||
|
return NewError("bad arg in system call")
|
||||||
|
}
|
||||||
|
var pp [2]_C_int
|
||||||
|
err = pipe(&pp)
|
||||||
|
p[0] = int(pp[0])
|
||||||
|
p[1] = int(pp[1])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//sys sleep(millisecs int32) (err Error)
|
||||||
|
func Sleep(nsec int64) (err Error) {
|
||||||
|
return sleep(int32((nsec + 999) / 1e6)) // round up to microsecond
|
||||||
|
}
|
||||||
|
|
||||||
|
// Underlying system call writes to newoffset via pointer.
|
||||||
|
// Implemented in assembly to avoid allocation.
|
||||||
|
func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
|
||||||
|
|
||||||
|
func Seek(fd int, offset int64, whence int) (newoffset int64, err Error) {
|
||||||
|
newoffset, e := seek(0, fd, offset, whence)
|
||||||
|
|
||||||
|
err = nil
|
||||||
|
if newoffset == -1 {
|
||||||
|
err = NewError(e)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Mkdir(path string, mode uint32) (err Error) {
|
||||||
|
fd, err := Create(path, O_RDONLY, DMDIR|mode)
|
||||||
|
|
||||||
|
if fd != -1 {
|
||||||
|
Close(fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type Waitmsg struct {
|
||||||
|
Pid int
|
||||||
|
Time [3]uint32
|
||||||
|
Msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys await(s []byte) (n int, err Error)
|
||||||
|
func Await(w *Waitmsg) (err Error) {
|
||||||
|
var buf [512]byte
|
||||||
|
var f [5][]byte
|
||||||
|
|
||||||
|
n, err := await(buf[:])
|
||||||
|
|
||||||
|
if err != nil || w == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
nf := 0
|
||||||
|
p := 0
|
||||||
|
for i := 0; i < n && nf < len(f)-1; i++ {
|
||||||
|
if buf[i] == ' ' {
|
||||||
|
f[nf] = buf[p:i]
|
||||||
|
p = i + 1
|
||||||
|
nf++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f[nf] = buf[p:]
|
||||||
|
nf++
|
||||||
|
|
||||||
|
if nf != len(f) {
|
||||||
|
return NewError("invalid wait message")
|
||||||
|
}
|
||||||
|
w.Pid = int(atoi(f[0]))
|
||||||
|
w.Time[0] = uint32(atoi(f[1]))
|
||||||
|
w.Time[1] = uint32(atoi(f[2]))
|
||||||
|
w.Time[2] = uint32(atoi(f[3]))
|
||||||
|
w.Msg = string(f[4])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Unmount(name, old string) (err Error) {
|
||||||
|
oldp := uintptr(unsafe.Pointer(StringBytePtr(old)))
|
||||||
|
|
||||||
|
var r0 uintptr
|
||||||
|
var e string
|
||||||
|
|
||||||
|
// bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
|
||||||
|
if name == "" {
|
||||||
|
r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldp, 0)
|
||||||
|
} else {
|
||||||
|
r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(name))), oldp, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Fchdir(fd int) (err Error) {
|
||||||
|
path, err := Fd2path(fd)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return Chdir(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Timeval struct {
|
||||||
|
Sec int32
|
||||||
|
Usec int32
|
||||||
|
}
|
||||||
|
|
||||||
|
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||||
|
nsec += 999 // round up to microsecond
|
||||||
|
tv.Usec = int32(nsec % 1e9 / 1e3)
|
||||||
|
tv.Sec = int32(nsec / 1e9)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecodeBintime(b []byte) (nsec int64, err Error) {
|
||||||
|
if len(b) != 8 {
|
||||||
|
return -1, NewError("bad /dev/bintime format")
|
||||||
|
}
|
||||||
|
err = nil
|
||||||
|
nsec = int64(b[0])<<56 |
|
||||||
|
int64(b[1])<<48 |
|
||||||
|
int64(b[2])<<40 |
|
||||||
|
int64(b[3])<<32 |
|
||||||
|
int64(b[4])<<24 |
|
||||||
|
int64(b[5])<<16 |
|
||||||
|
int64(b[6])<<8 |
|
||||||
|
int64(b[7])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Gettimeofday(tv *Timeval) (err Error) {
|
||||||
|
// TODO(paulzhol):
|
||||||
|
// avoid reopening a file descriptor for /dev/bintime on each call,
|
||||||
|
// use lower-level calls to avoid allocation.
|
||||||
|
|
||||||
|
var b [8]byte
|
||||||
|
var nsec int64
|
||||||
|
|
||||||
|
fd, e := Open("/dev/bintime", O_RDONLY)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
defer Close(fd)
|
||||||
|
|
||||||
|
if _, e = Pread(fd, b[:], 0); e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
if nsec, e = DecodeBintime(b[:]); e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
*tv = NsecToTimeval(nsec)
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getegid() (egid int) { return -1 }
|
||||||
|
func Geteuid() (euid int) { return -1 }
|
||||||
|
func Getgid() (gid int) { return -1 }
|
||||||
|
func Getuid() (uid int) { return -1 }
|
||||||
|
|
||||||
|
func Getgroups() (gids []int, err Error) {
|
||||||
|
return make([]int, 0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys Dup(oldfd int, newfd int) (fd int, err Error)
|
||||||
|
//sys Open(path string, mode int) (fd int, err Error)
|
||||||
|
//sys Create(path string, mode int, perm uint32) (fd int, err Error)
|
||||||
|
//sys Remove(path string) (err Error)
|
||||||
|
//sys Pread(fd int, p []byte, offset int64) (n int, err Error)
|
||||||
|
//sys Pwrite(fd int, p []byte, offset int64) (n int, err Error)
|
||||||
|
//sys Close(fd int) (err Error)
|
||||||
|
//sys Chdir(path string) (err Error)
|
||||||
|
//sys Bind(name string, old string, flag int) (err Error)
|
||||||
|
//sys Mount(fd int, afd int, old string, flag int, aname string) (err Error)
|
||||||
|
//sys Stat(path string, edir []byte) (n int, err Error)
|
||||||
|
//sys Fstat(fd int, edir []byte) (n int, err Error)
|
||||||
|
//sys Wstat(path string, edir []byte) (err Error)
|
||||||
|
//sys Fwstat(fd int, edir []byte) (err Error)
|
5
src/pkg/syscall/syscall_plan9_386.go
Normal file
5
src/pkg/syscall/syscall_plan9_386.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package syscall
|
@ -17,7 +17,7 @@ func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
|
|||||||
|
|
||||||
func Errstr(errno int) string {
|
func Errstr(errno int) string {
|
||||||
if errno < 0 || errno >= int(len(errors)) {
|
if errno < 0 || errno >= int(len(errors)) {
|
||||||
return "error " + str(errno)
|
return "error " + itoa(errno)
|
||||||
}
|
}
|
||||||
return errors[errno]
|
return errors[errno]
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ func Errstr(errno int) string {
|
|||||||
b := make([]uint16, 300)
|
b := make([]uint16, 300)
|
||||||
n, err := FormatMessage(flags, 0, uint32(errno), 0, b, nil)
|
n, err := FormatMessage(flags, 0, uint32(errno), 0, b, nil)
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return "error " + str(errno) + " (FormatMessage failed with err=" + str(err) + ")"
|
return "error " + itoa(errno) + " (FormatMessage failed with err=" + itoa(err) + ")"
|
||||||
}
|
}
|
||||||
// trim terminating \r and \n
|
// trim terminating \r and \n
|
||||||
for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- {
|
for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- {
|
||||||
|
115
src/pkg/syscall/types_plan9.c
Normal file
115
src/pkg/syscall/types_plan9.c
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Input to godefs. See also mkerrors.sh and mkall.sh
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef unsigned short ushort;
|
||||||
|
typedef unsigned char uchar;
|
||||||
|
typedef unsigned long ulong;
|
||||||
|
typedef unsigned int uint;
|
||||||
|
typedef long long vlong;
|
||||||
|
typedef unsigned long long uvlong;
|
||||||
|
|
||||||
|
typedef int $_C_int;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
OREAD = 0, // open for read
|
||||||
|
OWRITE = 1, // write
|
||||||
|
ORDWR = 2, // read and write
|
||||||
|
|
||||||
|
$O_RDONLY = OREAD,
|
||||||
|
$O_WRONLY = OWRITE,
|
||||||
|
$O_RDWR = ORDWR,
|
||||||
|
|
||||||
|
OEXEC = 3, // execute, == read but check execute permission
|
||||||
|
OTRUNC = 16, // or'ed in (except for exec), truncate file first
|
||||||
|
OCEXEC = 32, // or'ed in, close on exec
|
||||||
|
|
||||||
|
$O_CLOEXEC = OCEXEC,
|
||||||
|
|
||||||
|
ORCLOSE = 64, // or'ed in, remove on close
|
||||||
|
OEXCL = 0x1000, // or'ed in, exclusive use (create only)
|
||||||
|
$O_EXCL = OEXCL,
|
||||||
|
|
||||||
|
$STATMAX = 65535U,
|
||||||
|
$ERRMAX = 128,
|
||||||
|
|
||||||
|
$MORDER = 0x0003, // mask for bits defining order of mounting
|
||||||
|
$MREPL = 0x0000, // mount replaces object
|
||||||
|
$MBEFORE = 0x0001, // mount goes before others in union directory
|
||||||
|
$MAFTER = 0x0002, // mount goes after others in union directory
|
||||||
|
$MCREATE = 0x0004, // permit creation in mounted directory
|
||||||
|
$MCACHE = 0x0010, // cache some data
|
||||||
|
$MMASK = 0x0017, // all bits on
|
||||||
|
|
||||||
|
$RFNAMEG = (1<<0),
|
||||||
|
$RFENVG = (1<<1),
|
||||||
|
$RFFDG = (1<<2),
|
||||||
|
$RFNOTEG = (1<<3),
|
||||||
|
$RFPROC = (1<<4),
|
||||||
|
$RFMEM = (1<<5),
|
||||||
|
$RFNOWAIT = (1<<6),
|
||||||
|
$RFCNAMEG = (1<<10),
|
||||||
|
$RFCENVG = (1<<11),
|
||||||
|
$RFCFDG = (1<<12),
|
||||||
|
$RFREND = (1<<13),
|
||||||
|
$RFNOMNT = (1<<14),
|
||||||
|
|
||||||
|
// bits in Qid.type
|
||||||
|
$QTDIR = 0x80, // type bit for directories
|
||||||
|
$QTAPPEND = 0x40, // type bit for append only files
|
||||||
|
$QTEXCL = 0x20, // type bit for exclusive use files
|
||||||
|
$QTMOUNT = 0x10, // type bit for mounted channel
|
||||||
|
$QTAUTH = 0x08, // type bit for authentication file
|
||||||
|
$QTTMP = 0x04, // type bit for not-backed-up file
|
||||||
|
$QTFILE = 0x00, // plain file
|
||||||
|
|
||||||
|
|
||||||
|
// bits in Dir.mode
|
||||||
|
$DMDIR = 0x80000000, // mode bit for directories
|
||||||
|
$DMAPPEND = 0x40000000, // mode bit for append only files
|
||||||
|
$DMEXCL = 0x20000000, // mode bit for exclusive use files
|
||||||
|
$DMMOUNT = 0x10000000, // mode bit for mounted channel
|
||||||
|
$DMAUTH = 0x08000000, // mode bit for authentication file
|
||||||
|
$DMTMP = 0x04000000, // mode bit for non-backed-up files
|
||||||
|
$DMREAD = 0x4, // mode bit for read permission
|
||||||
|
$DMWRITE = 0x2, // mode bit for write permission
|
||||||
|
$DMEXEC = 0x1, // mode bit for execute permission
|
||||||
|
|
||||||
|
BIT8SZ = 1,
|
||||||
|
BIT16SZ = 2,
|
||||||
|
BIT32SZ = 4,
|
||||||
|
BIT64SZ = 8,
|
||||||
|
QIDSZ = BIT8SZ+BIT32SZ+BIT64SZ,
|
||||||
|
|
||||||
|
// STATFIXLEN includes leading 16-bit count
|
||||||
|
// The count, however, excludes itself; total size is BIT16SZ+count
|
||||||
|
$STATFIXLEN = BIT16SZ+QIDSZ+5*BIT16SZ+4*BIT32SZ+1*BIT64SZ, // amount of fixed length data in a stat buffer
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct Prof // Per process profiling
|
||||||
|
{
|
||||||
|
struct Plink *pp; // known to be 0(ptr)
|
||||||
|
struct Plink *next; // known to be 4(ptr)
|
||||||
|
struct Plink *last;
|
||||||
|
struct Plink *first;
|
||||||
|
ulong pid;
|
||||||
|
ulong what;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Tos {
|
||||||
|
struct Prof prof;
|
||||||
|
uvlong cyclefreq; // cycle clock frequency if there is one, 0 otherwise
|
||||||
|
vlong kcycles; // cycles spent in kernel
|
||||||
|
vlong pcycles; // cycles spent in process (kernel + user)
|
||||||
|
ulong pid; // might as well put the pid here
|
||||||
|
ulong clock;
|
||||||
|
// top of stack is here
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Prof $Prof;
|
||||||
|
typedef struct Tos $Tos;
|
25
src/pkg/syscall/zerrors_plan9_386.go
Normal file
25
src/pkg/syscall/zerrors_plan9_386.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package syscall
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const (
|
||||||
|
// Invented values to support what package os expects.
|
||||||
|
O_CREAT = 0x02000
|
||||||
|
O_NOCTTY = 0x00000
|
||||||
|
O_TRUNC = 0x00000
|
||||||
|
O_NONBLOCK = 0x00000
|
||||||
|
O_APPEND = 0x00000
|
||||||
|
O_SYNC = 0x00000
|
||||||
|
O_ASYNC = 0x00000
|
||||||
|
|
||||||
|
|
||||||
|
S_IFMT = 0x1f000
|
||||||
|
S_IFIFO = 0x1000
|
||||||
|
S_IFCHR = 0x2000
|
||||||
|
S_IFDIR = 0x4000
|
||||||
|
S_IFBLK = 0x6000
|
||||||
|
S_IFREG = 0x8000
|
||||||
|
S_IFLNK = 0xa000
|
||||||
|
S_IFSOCK = 0xc000
|
||||||
|
)
|
||||||
|
|
||||||
|
// Error table
|
267
src/pkg/syscall/zsyscall_plan9_386.go
Normal file
267
src/pkg/syscall/zsyscall_plan9_386.go
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
// mksyscall.pl -l32 -plan9 syscall_plan9.go syscall_plan9_386.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package syscall
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func exits(msg *byte) {
|
||||||
|
Syscall(SYS_EXITS, uintptr(unsafe.Pointer(msg)), 0, 0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func fd2path(fd int, buf []byte) (err Error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(buf) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&buf[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func pipe(p *[2]_C_int) (err Error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func sleep(millisecs int32) (err Error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_SLEEP, uintptr(millisecs), 0, 0)
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func await(s []byte) (n int, err Error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(s) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&s[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
|
||||||
|
n = int(r0)
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Dup(oldfd int, newfd int) (fd int, err Error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
|
||||||
|
fd = int(r0)
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Open(path string, mode int) (fd int, err Error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
|
||||||
|
fd = int(r0)
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Create(path string, mode int, perm uint32) (fd int, err Error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
|
||||||
|
fd = int(r0)
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Remove(path string) (err Error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Pread(fd int, p []byte, offset int64) (n int, err Error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(p) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&p[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
|
||||||
|
n = int(r0)
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Pwrite(fd int, p []byte, offset int64) (n int, err Error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(p) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&p[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
|
||||||
|
n = int(r0)
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Close(fd int) (err Error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Chdir(path string) (err Error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Bind(name string, old string, flag int) (err Error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(StringBytePtr(name))), uintptr(unsafe.Pointer(StringBytePtr(old))), uintptr(flag))
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Mount(fd int, afd int, old string, flag int, aname string) (err Error) {
|
||||||
|
r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(StringBytePtr(old))), uintptr(flag), uintptr(unsafe.Pointer(StringBytePtr(aname))), 0)
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Stat(path string, edir []byte) (n int, err Error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(edir)))
|
||||||
|
n = int(r0)
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Fstat(fd int, edir []byte) (n int, err Error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
|
||||||
|
n = int(r0)
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Wstat(path string, edir []byte) (err Error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(edir)))
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Fwstat(fd int, edir []byte) (err Error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
|
||||||
|
err = nil
|
||||||
|
if int(r0) == -1 {
|
||||||
|
err = NewError(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
47
src/pkg/syscall/zsysnum_plan9_386.go
Normal file
47
src/pkg/syscall/zsysnum_plan9_386.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// mksysnum_plan9.sh /media/sys/src/libc/9syscall/sys.h
|
||||||
|
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
|
||||||
|
|
||||||
|
package syscall
|
||||||
|
|
||||||
|
const (
|
||||||
|
SYS_SYSR1 = 0
|
||||||
|
SYS_BIND = 2
|
||||||
|
SYS_CHDIR = 3
|
||||||
|
SYS_CLOSE = 4
|
||||||
|
SYS_DUP = 5
|
||||||
|
SYS_ALARM = 6
|
||||||
|
SYS_EXEC = 7
|
||||||
|
SYS_EXITS = 8
|
||||||
|
SYS_FAUTH = 10
|
||||||
|
SYS_SEGBRK = 12
|
||||||
|
SYS_OPEN = 14
|
||||||
|
SYS_OSEEK = 16
|
||||||
|
SYS_SLEEP = 17
|
||||||
|
SYS_RFORK = 19
|
||||||
|
SYS_PIPE = 21
|
||||||
|
SYS_CREATE = 22
|
||||||
|
SYS_FD2PATH = 23
|
||||||
|
SYS_BRK_ = 24
|
||||||
|
SYS_REMOVE = 25
|
||||||
|
SYS_NOTIFY = 28
|
||||||
|
SYS_NOTED = 29
|
||||||
|
SYS_SEGATTACH = 30
|
||||||
|
SYS_SEGDETACH = 31
|
||||||
|
SYS_SEGFREE = 32
|
||||||
|
SYS_SEGFLUSH = 33
|
||||||
|
SYS_RENDEZVOUS = 34
|
||||||
|
SYS_UNMOUNT = 35
|
||||||
|
SYS_SEMACQUIRE = 37
|
||||||
|
SYS_SEMRELEASE = 38
|
||||||
|
SYS_SEEK = 39
|
||||||
|
SYS_FVERSION = 40
|
||||||
|
SYS_ERRSTR = 41
|
||||||
|
SYS_STAT = 42
|
||||||
|
SYS_FSTAT = 43
|
||||||
|
SYS_WSTAT = 44
|
||||||
|
SYS_FWSTAT = 45
|
||||||
|
SYS_MOUNT = 46
|
||||||
|
SYS_AWAIT = 47
|
||||||
|
SYS_PREAD = 50
|
||||||
|
SYS_PWRITE = 51
|
||||||
|
)
|
74
src/pkg/syscall/ztypes_plan9_386.go
Normal file
74
src/pkg/syscall/ztypes_plan9_386.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// godefs -gsyscall -f -m32 types_plan9.c
|
||||||
|
|
||||||
|
// MACHINE GENERATED - DO NOT EDIT.
|
||||||
|
|
||||||
|
package syscall
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const (
|
||||||
|
O_RDONLY = 0
|
||||||
|
O_WRONLY = 0x1
|
||||||
|
O_RDWR = 0x2
|
||||||
|
O_CLOEXEC = 0x20
|
||||||
|
O_EXCL = 0x1000
|
||||||
|
STATMAX = 0xffff
|
||||||
|
ERRMAX = 0x80
|
||||||
|
MORDER = 0x3
|
||||||
|
MREPL = 0
|
||||||
|
MBEFORE = 0x1
|
||||||
|
MAFTER = 0x2
|
||||||
|
MCREATE = 0x4
|
||||||
|
MCACHE = 0x10
|
||||||
|
MMASK = 0x17
|
||||||
|
RFNAMEG = 0x1
|
||||||
|
RFENVG = 0x2
|
||||||
|
RFFDG = 0x4
|
||||||
|
RFNOTEG = 0x8
|
||||||
|
RFPROC = 0x10
|
||||||
|
RFMEM = 0x20
|
||||||
|
RFNOWAIT = 0x40
|
||||||
|
RFCNAMEG = 0x400
|
||||||
|
RFCENVG = 0x800
|
||||||
|
RFCFDG = 0x1000
|
||||||
|
RFREND = 0x2000
|
||||||
|
RFNOMNT = 0x4000
|
||||||
|
QTDIR = 0x80
|
||||||
|
QTAPPEND = 0x40
|
||||||
|
QTEXCL = 0x20
|
||||||
|
QTMOUNT = 0x10
|
||||||
|
QTAUTH = 0x8
|
||||||
|
QTTMP = 0x4
|
||||||
|
QTFILE = 0
|
||||||
|
DMDIR = 0x80000000
|
||||||
|
DMAPPEND = 0x40000000
|
||||||
|
DMEXCL = 0x20000000
|
||||||
|
DMMOUNT = 0x10000000
|
||||||
|
DMAUTH = 0x8000000
|
||||||
|
DMTMP = 0x4000000
|
||||||
|
DMREAD = 0x4
|
||||||
|
DMWRITE = 0x2
|
||||||
|
DMEXEC = 0x1
|
||||||
|
STATFIXLEN = 0x31
|
||||||
|
)
|
||||||
|
|
||||||
|
// Types
|
||||||
|
|
||||||
|
type _C_int int32
|
||||||
|
|
||||||
|
type Prof struct {
|
||||||
|
Pp *[0]byte /* sPlink */
|
||||||
|
Next *[0]byte /* sPlink */
|
||||||
|
Last *[0]byte /* sPlink */
|
||||||
|
First *[0]byte /* sPlink */
|
||||||
|
Pid uint32
|
||||||
|
What uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tos struct {
|
||||||
|
Prof Prof
|
||||||
|
Cyclefreq uint64
|
||||||
|
Kcycles int64
|
||||||
|
Pcycles int64
|
||||||
|
Pid uint32
|
||||||
|
Clock uint32
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user