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