Source file src/syscall/syscall_plan9.go

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

View as plain text