257 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Go
		
	
	
	
// Copyright 2013 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 linux
 | 
						||
 | 
						||
package interp
 | 
						||
 | 
						||
import "syscall"
 | 
						||
 | 
						||
func init() {
 | 
						||
	for k, v := range map[string]externalFn{
 | 
						||
		"os.Pipe":              ext۰os۰Pipe,
 | 
						||
		"syscall.Close":        ext۰syscall۰Close,
 | 
						||
		"syscall.Exit":         ext۰syscall۰Exit,
 | 
						||
		"syscall.Fchown":       ext۰syscall۰Fchown,
 | 
						||
		"syscall.Fstat":        ext۰syscall۰Fstat,
 | 
						||
		"syscall.Ftruncate":    ext۰syscall۰Ftruncate,
 | 
						||
		"syscall.Getpid":       ext۰syscall۰Getpid,
 | 
						||
		"syscall.Getwd":        ext۰syscall۰Getwd,
 | 
						||
		"syscall.Kill":         ext۰syscall۰Kill,
 | 
						||
		"syscall.Link":         ext۰syscall۰Link,
 | 
						||
		"syscall.Lstat":        ext۰syscall۰Lstat,
 | 
						||
		"syscall.Mkdir":        ext۰syscall۰Mkdir,
 | 
						||
		"syscall.Open":         ext۰syscall۰Open,
 | 
						||
		"syscall.ParseDirent":  ext۰syscall۰ParseDirent,
 | 
						||
		"syscall.RawSyscall":   ext۰syscall۰RawSyscall,
 | 
						||
		"syscall.Read":         ext۰syscall۰Read,
 | 
						||
		"syscall.ReadDirent":   ext۰syscall۰ReadDirent,
 | 
						||
		"syscall.Readlink":     ext۰syscall۰Readlink,
 | 
						||
		"syscall.Rmdir":        ext۰syscall۰Rmdir,
 | 
						||
		"syscall.Seek":         ext۰syscall۰Seek,
 | 
						||
		"syscall.Stat":         ext۰syscall۰Stat,
 | 
						||
		"syscall.Symlink":      ext۰syscall۰Symlink,
 | 
						||
		"syscall.Write":        ext۰syscall۰Write,
 | 
						||
		"syscall.Unlink":       ext۰syscall۰Unlink,
 | 
						||
		"syscall۰UtimesNano":   ext۰syscall۰UtimesNano,
 | 
						||
		"syscall.setenv_c":     ext۰nop,
 | 
						||
		"syscall.unsetenv_c":   ext۰nop,
 | 
						||
		"syscall.runtime_envs": ext۰runtime۰environ,
 | 
						||
	} {
 | 
						||
		externals[k] = v
 | 
						||
	}
 | 
						||
 | 
						||
	syswrite = syscall.Write
 | 
						||
}
 | 
						||
 | 
						||
func ext۰os۰Pipe(fr *frame, args []value) value {
 | 
						||
	// func os.Pipe() (r *File, w *File, err error)
 | 
						||
 | 
						||
	// The portable POSIX pipe(2) call is good enough for our needs.
 | 
						||
	var p [2]int
 | 
						||
	if err := syscall.Pipe(p[:]); err != nil {
 | 
						||
		// TODO(adonovan): fix: return an *os.SyscallError.
 | 
						||
		return tuple{nil, nil, wrapError(err)}
 | 
						||
	}
 | 
						||
 | 
						||
	NewFile := fr.i.prog.ImportedPackage("os").Func("NewFile")
 | 
						||
	r := call(fr.i, fr, 0, NewFile, []value{uintptr(p[0]), "|0"})
 | 
						||
	w := call(fr.i, fr, 0, NewFile, []value{uintptr(p[1]), "|1"})
 | 
						||
	return tuple{r, w, wrapError(nil)}
 | 
						||
}
 | 
						||
 | 
						||
// overridden on darwin
 | 
						||
var fillStat = func(st *syscall.Stat_t, stat structure) {
 | 
						||
	stat[0] = st.Dev
 | 
						||
	stat[1] = st.Ino
 | 
						||
	stat[2] = st.Nlink
 | 
						||
	stat[3] = st.Mode
 | 
						||
	stat[4] = st.Uid
 | 
						||
	stat[5] = st.Gid
 | 
						||
	stat[7] = st.Rdev
 | 
						||
	stat[8] = st.Size
 | 
						||
	stat[9] = st.Blksize
 | 
						||
	stat[10] = st.Blocks
 | 
						||
	// TODO(adonovan): fix: copy Timespecs.
 | 
						||
	// stat[11] = st.Atim
 | 
						||
	// stat[12] = st.Mtim
 | 
						||
	// stat[13] = st.Ctim
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Close(fr *frame, args []value) value {
 | 
						||
	// func Close(fd int) (err error)
 | 
						||
	return wrapError(syscall.Close(args[0].(int)))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Exit(fr *frame, args []value) value {
 | 
						||
	panic(exitPanic(args[0].(int)))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Fchown(fr *frame, args []value) value {
 | 
						||
	fd := args[0].(int)
 | 
						||
	uid := args[1].(int)
 | 
						||
	gid := args[2].(int)
 | 
						||
	return wrapError(syscall.Fchown(fd, uid, gid))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Fstat(fr *frame, args []value) value {
 | 
						||
	// func Fstat(fd int, stat *Stat_t) (err error)
 | 
						||
	fd := args[0].(int)
 | 
						||
	stat := (*args[1].(*value)).(structure)
 | 
						||
 | 
						||
	var st syscall.Stat_t
 | 
						||
	err := syscall.Fstat(fd, &st)
 | 
						||
	fillStat(&st, stat)
 | 
						||
	return wrapError(err)
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Ftruncate(fr *frame, args []value) value {
 | 
						||
	fd := args[0].(int)
 | 
						||
	length := args[1].(int64)
 | 
						||
	return wrapError(syscall.Ftruncate(fd, length))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Getpid(fr *frame, args []value) value {
 | 
						||
	return syscall.Getpid()
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Getwd(fr *frame, args []value) value {
 | 
						||
	s, err := syscall.Getwd()
 | 
						||
	return tuple{s, wrapError(err)}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Kill(fr *frame, args []value) value {
 | 
						||
	// func Kill(pid int, sig Signal) (err error)
 | 
						||
	return wrapError(syscall.Kill(args[0].(int), syscall.Signal(args[1].(int))))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Link(fr *frame, args []value) value {
 | 
						||
	path := args[0].(string)
 | 
						||
	link := args[1].(string)
 | 
						||
	return wrapError(syscall.Link(path, link))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Lstat(fr *frame, args []value) value {
 | 
						||
	// func Lstat(name string, stat *Stat_t) (err error)
 | 
						||
	name := args[0].(string)
 | 
						||
	stat := (*args[1].(*value)).(structure)
 | 
						||
 | 
						||
	var st syscall.Stat_t
 | 
						||
	err := syscall.Lstat(name, &st)
 | 
						||
	fillStat(&st, stat)
 | 
						||
	return wrapError(err)
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Mkdir(fr *frame, args []value) value {
 | 
						||
	path := args[0].(string)
 | 
						||
	mode := args[1].(uint32)
 | 
						||
	return wrapError(syscall.Mkdir(path, mode))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Open(fr *frame, args []value) value {
 | 
						||
	// func Open(path string, mode int, perm uint32) (fd int, err error) {
 | 
						||
	path := args[0].(string)
 | 
						||
	mode := args[1].(int)
 | 
						||
	perm := args[2].(uint32)
 | 
						||
	fd, err := syscall.Open(path, mode, perm)
 | 
						||
	return tuple{fd, wrapError(err)}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰ParseDirent(fr *frame, args []value) value {
 | 
						||
	// func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string)
 | 
						||
	max := args[1].(int)
 | 
						||
	var names []string
 | 
						||
	for _, iname := range args[2].([]value) {
 | 
						||
		names = append(names, iname.(string))
 | 
						||
	}
 | 
						||
	consumed, count, newnames := syscall.ParseDirent(valueToBytes(args[0]), max, names)
 | 
						||
	var inewnames []value
 | 
						||
	for _, newname := range newnames {
 | 
						||
		inewnames = append(inewnames, newname)
 | 
						||
	}
 | 
						||
	return tuple{consumed, count, inewnames}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰RawSyscall(fr *frame, args []value) value {
 | 
						||
	return tuple{uintptr(0), uintptr(0), uintptr(syscall.ENOSYS)}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Read(fr *frame, args []value) value {
 | 
						||
	// func Read(fd int, p []byte) (n int, err error)
 | 
						||
	fd := args[0].(int)
 | 
						||
	p := args[1].([]value)
 | 
						||
	b := make([]byte, len(p))
 | 
						||
	n, err := syscall.Read(fd, b)
 | 
						||
	for i := 0; i < n; i++ {
 | 
						||
		p[i] = b[i]
 | 
						||
	}
 | 
						||
	return tuple{n, wrapError(err)}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰ReadDirent(fr *frame, args []value) value {
 | 
						||
	// func ReadDirent(fd int, buf []byte) (n int, err error)
 | 
						||
	fd := args[0].(int)
 | 
						||
	p := args[1].([]value)
 | 
						||
	b := make([]byte, len(p))
 | 
						||
	n, err := syscall.ReadDirent(fd, b)
 | 
						||
	for i := 0; i < n; i++ {
 | 
						||
		p[i] = b[i]
 | 
						||
	}
 | 
						||
	return tuple{n, wrapError(err)}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Readlink(fr *frame, args []value) value {
 | 
						||
	path := args[0].(string)
 | 
						||
	buf := valueToBytes(args[1])
 | 
						||
	n, err := syscall.Readlink(path, buf)
 | 
						||
	return tuple{n, wrapError(err)}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Rmdir(fr *frame, args []value) value {
 | 
						||
	return wrapError(syscall.Rmdir(args[0].(string)))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Seek(fr *frame, args []value) value {
 | 
						||
	fd := args[0].(int)
 | 
						||
	offset := args[1].(int64)
 | 
						||
	whence := args[2].(int)
 | 
						||
	new, err := syscall.Seek(fd, offset, whence)
 | 
						||
	return tuple{new, wrapError(err)}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Stat(fr *frame, args []value) value {
 | 
						||
	// func Stat(name string, stat *Stat_t) (err error)
 | 
						||
	name := args[0].(string)
 | 
						||
	stat := (*args[1].(*value)).(structure)
 | 
						||
 | 
						||
	var st syscall.Stat_t
 | 
						||
	err := syscall.Stat(name, &st)
 | 
						||
	fillStat(&st, stat)
 | 
						||
	return wrapError(err)
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Symlink(fr *frame, args []value) value {
 | 
						||
	path := args[0].(string)
 | 
						||
	link := args[1].(string)
 | 
						||
	return wrapError(syscall.Symlink(path, link))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Unlink(fr *frame, args []value) value {
 | 
						||
	return wrapError(syscall.Unlink(args[0].(string)))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰UtimesNano(fr *frame, args []value) value {
 | 
						||
	path := args[0].(string)
 | 
						||
	var ts [2]syscall.Timespec
 | 
						||
	err := syscall.UtimesNano(path, ts[:])
 | 
						||
	// TODO(adonovan): copy the Timespecs into args[1]
 | 
						||
	return wrapError(err)
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Write(fr *frame, args []value) value {
 | 
						||
	// func Write(fd int, p []byte) (n int, err error)
 | 
						||
	n, err := write(args[0].(int), valueToBytes(args[1]))
 | 
						||
	return tuple{n, wrapError(err)}
 | 
						||
}
 |