...
Run Format

Source file src/syscall/syscall_plan9.go

Documentation: syscall

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

View as plain text