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