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