github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/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  		use(unsafe.Pointer(namep))
   255  	}
   256  	use(unsafe.Pointer(oldp))
   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)