github.com/Filosottile/go@v0.0.0-20170906193555-dbed9972d994/src/syscall/syscall_plan9.go (about)

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