syscall_plan9.go raw

   1  // Copyright 2011 The Go Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  // Plan 9 system calls.
   6  // This file is compiled as ordinary Go code,
   7  // but it is also input to mksyscall,
   8  // which parses the //sys lines and generates system call stubs.
   9  // Note that sometimes we use a lowercase //sys name and
  10  // wrap it in our own nicer implementation.
  11  
  12  package plan9
  13  
  14  import (
  15  	"bytes"
  16  	"syscall"
  17  	"unsafe"
  18  )
  19  
  20  // A Note is a string describing a process note.
  21  // It implements the os.Signal interface.
  22  type Note string
  23  
  24  func (n Note) Signal() {}
  25  
  26  func (n Note) String() string {
  27  	return string(n)
  28  }
  29  
  30  var (
  31  	Stdin  = 0
  32  	Stdout = 1
  33  	Stderr = 2
  34  )
  35  
  36  // For testing: clients can set this flag to force
  37  // creation of IPv6 sockets to return EAFNOSUPPORT.
  38  var SocketDisableIPv6 bool
  39  
  40  func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.ErrorString)
  41  func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.ErrorString)
  42  func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
  43  func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
  44  
  45  func atoi(b []byte) (n uint) {
  46  	n = 0
  47  	for i := 0; i < len(b); i++ {
  48  		n = n*10 + uint(b[i]-'0')
  49  	}
  50  	return
  51  }
  52  
  53  func cstring(s []byte) string {
  54  	i := bytes.IndexByte(s, 0)
  55  	if i == -1 {
  56  		i = len(s)
  57  	}
  58  	return string(s[:i])
  59  }
  60  
  61  func errstr() string {
  62  	var buf [ERRMAX]byte
  63  
  64  	RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)
  65  
  66  	buf[len(buf)-1] = 0
  67  	return cstring(buf[:])
  68  }
  69  
  70  // Implemented in assembly to import from runtime.
  71  func exit(code int)
  72  
  73  func Exit(code int) { exit(code) }
  74  
  75  func readnum(path string) (uint, error) {
  76  	var b [12]byte
  77  
  78  	fd, e := Open(path, O_RDONLY)
  79  	if e != nil {
  80  		return 0, e
  81  	}
  82  	defer Close(fd)
  83  
  84  	n, e := Pread(fd, b[:], 0)
  85  
  86  	if e != nil {
  87  		return 0, e
  88  	}
  89  
  90  	m := 0
  91  	for ; m < n && b[m] == ' '; m++ {
  92  	}
  93  
  94  	return atoi(b[m : n-1]), nil
  95  }
  96  
  97  func Getpid() (pid int) {
  98  	n, _ := readnum("#c/pid")
  99  	return int(n)
 100  }
 101  
 102  func Getppid() (ppid int) {
 103  	n, _ := readnum("#c/ppid")
 104  	return int(n)
 105  }
 106  
 107  func Read(fd int, p []byte) (n int, err error) {
 108  	return Pread(fd, p, -1)
 109  }
 110  
 111  func Write(fd int, p []byte) (n int, err error) {
 112  	return Pwrite(fd, p, -1)
 113  }
 114  
 115  var ioSync int64
 116  
 117  //sys	fd2path(fd int, buf []byte) (err error)
 118  
 119  func Fd2path(fd int) (path string, err error) {
 120  	var buf [512]byte
 121  
 122  	e := fd2path(fd, buf[:])
 123  	if e != nil {
 124  		return "", e
 125  	}
 126  	return cstring(buf[:]), nil
 127  }
 128  
 129  //sys	pipe(p *[2]int32) (err error)
 130  
 131  func Pipe(p []int) (err error) {
 132  	if len(p) != 2 {
 133  		return syscall.ErrorString("bad arg in system call")
 134  	}
 135  	var pp [2]int32
 136  	err = pipe(&pp)
 137  	if err == nil {
 138  		p[0] = int(pp[0])
 139  		p[1] = int(pp[1])
 140  	}
 141  	return
 142  }
 143  
 144  // Underlying system call writes to newoffset via pointer.
 145  // Implemented in assembly to avoid allocation.
 146  func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
 147  
 148  func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
 149  	newoffset, e := seek(0, fd, offset, whence)
 150  
 151  	if newoffset == -1 {
 152  		err = syscall.ErrorString(e)
 153  	}
 154  	return
 155  }
 156  
 157  func Mkdir(path string, mode uint32) (err error) {
 158  	fd, err := Create(path, O_RDONLY, DMDIR|mode)
 159  
 160  	if fd != -1 {
 161  		Close(fd)
 162  	}
 163  
 164  	return
 165  }
 166  
 167  type Waitmsg struct {
 168  	Pid  int
 169  	Time [3]uint32
 170  	Msg  string
 171  }
 172  
 173  func (w Waitmsg) Exited() bool   { return true }
 174  func (w Waitmsg) Signaled() bool { return false }
 175  
 176  func (w Waitmsg) ExitStatus() int {
 177  	if len(w.Msg) == 0 {
 178  		// a normal exit returns no message
 179  		return 0
 180  	}
 181  	return 1
 182  }
 183  
 184  //sys	await(s []byte) (n int, err error)
 185  
 186  func Await(w *Waitmsg) (err error) {
 187  	var buf [512]byte
 188  	var f [5][]byte
 189  
 190  	n, err := await(buf[:])
 191  
 192  	if err != nil || w == nil {
 193  		return
 194  	}
 195  
 196  	nf := 0
 197  	p := 0
 198  	for i := 0; i < n && nf < len(f)-1; i++ {
 199  		if buf[i] == ' ' {
 200  			f[nf] = buf[p:i]
 201  			p = i + 1
 202  			nf++
 203  		}
 204  	}
 205  	f[nf] = buf[p:]
 206  	nf++
 207  
 208  	if nf != len(f) {
 209  		return syscall.ErrorString("invalid wait message")
 210  	}
 211  	w.Pid = int(atoi(f[0]))
 212  	w.Time[0] = uint32(atoi(f[1]))
 213  	w.Time[1] = uint32(atoi(f[2]))
 214  	w.Time[2] = uint32(atoi(f[3]))
 215  	w.Msg = cstring(f[4])
 216  	if w.Msg == "''" {
 217  		// await() returns '' for no error
 218  		w.Msg = ""
 219  	}
 220  	return
 221  }
 222  
 223  func Unmount(name, old string) (err error) {
 224  	fixwd()
 225  	oldp, err := BytePtrFromString(old)
 226  	if err != nil {
 227  		return err
 228  	}
 229  	oldptr := uintptr(unsafe.Pointer(oldp))
 230  
 231  	var r0 uintptr
 232  	var e syscall.ErrorString
 233  
 234  	// bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
 235  	if name == "" {
 236  		r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldptr, 0)
 237  	} else {
 238  		namep, err := BytePtrFromString(name)
 239  		if err != nil {
 240  			return err
 241  		}
 242  		r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0)
 243  	}
 244  
 245  	if int32(r0) == -1 {
 246  		err = e
 247  	}
 248  	return
 249  }
 250  
 251  func Fchdir(fd int) (err error) {
 252  	path, err := Fd2path(fd)
 253  
 254  	if err != nil {
 255  		return
 256  	}
 257  
 258  	return Chdir(path)
 259  }
 260  
 261  type Timespec struct {
 262  	Sec  int32
 263  	Nsec int32
 264  }
 265  
 266  type Timeval struct {
 267  	Sec  int32
 268  	Usec int32
 269  }
 270  
 271  func NsecToTimeval(nsec int64) (tv Timeval) {
 272  	nsec += 999 // round up to microsecond
 273  	tv.Usec = int32(nsec % 1e9 / 1e3)
 274  	tv.Sec = int32(nsec / 1e9)
 275  	return
 276  }
 277  
 278  func nsec() int64 {
 279  	var scratch int64
 280  
 281  	r0, _, _ := Syscall(SYS_NSEC, uintptr(unsafe.Pointer(&scratch)), 0, 0)
 282  	// TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
 283  	if r0 == 0 {
 284  		return scratch
 285  	}
 286  	return int64(r0)
 287  }
 288  
 289  func Gettimeofday(tv *Timeval) error {
 290  	nsec := nsec()
 291  	*tv = NsecToTimeval(nsec)
 292  	return nil
 293  }
 294  
 295  func Getpagesize() int { return 0x1000 }
 296  
 297  func Getegid() (egid int) { return -1 }
 298  func Geteuid() (euid int) { return -1 }
 299  func Getgid() (gid int)   { return -1 }
 300  func Getuid() (uid int)   { return -1 }
 301  
 302  func Getgroups() (gids []int, err error) {
 303  	return make([]int, 0), nil
 304  }
 305  
 306  //sys	open(path string, mode int) (fd int, err error)
 307  
 308  func Open(path string, mode int) (fd int, err error) {
 309  	fixwd()
 310  	return open(path, mode)
 311  }
 312  
 313  //sys	create(path string, mode int, perm uint32) (fd int, err error)
 314  
 315  func Create(path string, mode int, perm uint32) (fd int, err error) {
 316  	fixwd()
 317  	return create(path, mode, perm)
 318  }
 319  
 320  //sys	remove(path string) (err error)
 321  
 322  func Remove(path string) error {
 323  	fixwd()
 324  	return remove(path)
 325  }
 326  
 327  //sys	stat(path string, edir []byte) (n int, err error)
 328  
 329  func Stat(path string, edir []byte) (n int, err error) {
 330  	fixwd()
 331  	return stat(path, edir)
 332  }
 333  
 334  //sys	bind(name string, old string, flag int) (err error)
 335  
 336  func Bind(name string, old string, flag int) (err error) {
 337  	fixwd()
 338  	return bind(name, old, flag)
 339  }
 340  
 341  //sys	mount(fd int, afd int, old string, flag int, aname string) (err error)
 342  
 343  func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
 344  	fixwd()
 345  	return mount(fd, afd, old, flag, aname)
 346  }
 347  
 348  //sys	wstat(path string, edir []byte) (err error)
 349  
 350  func Wstat(path string, edir []byte) (err error) {
 351  	fixwd()
 352  	return wstat(path, edir)
 353  }
 354  
 355  //sys	chdir(path string) (err error)
 356  //sys	Dup(oldfd int, newfd int) (fd int, err error)
 357  //sys	Pread(fd int, p []byte, offset int64) (n int, err error)
 358  //sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
 359  //sys	Close(fd int) (err error)
 360  //sys	Fstat(fd int, edir []byte) (n int, err error)
 361  //sys	Fwstat(fd int, edir []byte) (err error)
 362