syscall_wasip1.mx raw

   1  // Copyright 2023 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  //go:build wasip1
   6  
   7  package syscall
   8  
   9  import (
  10  	"errors"
  11  	"internal/itoa"
  12  	"internal/oserror"
  13  	"unsafe"
  14  )
  15  
  16  type Dircookie = uint64
  17  
  18  type Filetype = uint8
  19  
  20  const (
  21  	FILETYPE_UNKNOWN Filetype = iota
  22  	FILETYPE_BLOCK_DEVICE
  23  	FILETYPE_CHARACTER_DEVICE
  24  	FILETYPE_DIRECTORY
  25  	FILETYPE_REGULAR_FILE
  26  	FILETYPE_SOCKET_DGRAM
  27  	FILETYPE_SOCKET_STREAM
  28  	FILETYPE_SYMBOLIC_LINK
  29  )
  30  
  31  type Dirent struct {
  32  	// The offset of the next directory entry stored in this directory.
  33  	Next Dircookie
  34  	// The serial number of the file referred to by this directory entry.
  35  	Ino uint64
  36  	// The length of the name of the directory entry.
  37  	Namlen uint32
  38  	// The type of the file referred to by this directory entry.
  39  	Type Filetype
  40  	// Name of the directory entry.
  41  	Name *byte
  42  }
  43  
  44  func direntIno(buf []byte) (uint64, bool) {
  45  	return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
  46  }
  47  
  48  func direntReclen(buf []byte) (uint64, bool) {
  49  	namelen, ok := direntNamlen(buf)
  50  	return 24 + namelen, ok
  51  }
  52  
  53  func direntNamlen(buf []byte) (uint64, bool) {
  54  	return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
  55  }
  56  
  57  // An Errno is an unsigned number describing an error condition.
  58  // It implements the error interface. The zero Errno is by convention
  59  // a non-error, so code to convert from Errno to error should use:
  60  //
  61  //	var err = nil
  62  //	if errno != 0 {
  63  //		err = errno
  64  //	}
  65  type Errno uint32
  66  
  67  func (e Errno) Error() string {
  68  	if 0 <= int(e) && int(e) < len(errorstr) {
  69  		s := errorstr[e]
  70  		if s != "" {
  71  			return s
  72  		}
  73  	}
  74  	return "errno " + itoa.Itoa(int(e))
  75  }
  76  
  77  func (e Errno) Is(target error) bool {
  78  	switch target {
  79  	case oserror.ErrPermission:
  80  		return e == EACCES || e == EPERM
  81  	case oserror.ErrExist:
  82  		return e == EEXIST || e == ENOTEMPTY
  83  	case oserror.ErrNotExist:
  84  		return e == ENOENT
  85  	case errors.ErrUnsupported:
  86  		return e == ENOSYS
  87  	}
  88  	return false
  89  }
  90  
  91  func (e Errno) Temporary() bool {
  92  	return e == EINTR || e == EMFILE || e.Timeout()
  93  }
  94  
  95  func (e Errno) Timeout() bool {
  96  	return e == EAGAIN || e == ETIMEDOUT
  97  }
  98  
  99  // A Signal is a number describing a process signal.
 100  // It implements the [os.Signal] interface.
 101  type Signal uint8
 102  
 103  const (
 104  	SIGNONE Signal = iota
 105  	SIGHUP
 106  	SIGINT
 107  	SIGQUIT
 108  	SIGILL
 109  	SIGTRAP
 110  	SIGABRT
 111  	SIGBUS
 112  	SIGFPE
 113  	SIGKILL
 114  	SIGUSR1
 115  	SIGSEGV
 116  	SIGUSR2
 117  	SIGPIPE
 118  	SIGALRM
 119  	SIGTERM
 120  	SIGCHLD
 121  	SIGCONT
 122  	SIGSTOP
 123  	SIGTSTP
 124  	SIGTTIN
 125  	SIGTTOU
 126  	SIGURG
 127  	SIGXCPU
 128  	SIGXFSZ
 129  	SIGVTARLM
 130  	SIGPROF
 131  	SIGWINCH
 132  	SIGPOLL
 133  	SIGPWR
 134  	SIGSYS
 135  )
 136  
 137  func (s Signal) Signal() {}
 138  
 139  func (s Signal) String() string {
 140  	switch s {
 141  	case SIGNONE:
 142  		return "no signal"
 143  	case SIGHUP:
 144  		return "hangup"
 145  	case SIGINT:
 146  		return "interrupt"
 147  	case SIGQUIT:
 148  		return "quit"
 149  	case SIGILL:
 150  		return "illegal instruction"
 151  	case SIGTRAP:
 152  		return "trace/breakpoint trap"
 153  	case SIGABRT:
 154  		return "abort"
 155  	case SIGBUS:
 156  		return "bus error"
 157  	case SIGFPE:
 158  		return "floating point exception"
 159  	case SIGKILL:
 160  		return "killed"
 161  	case SIGUSR1:
 162  		return "user defined signal 1"
 163  	case SIGSEGV:
 164  		return "segmentation fault"
 165  	case SIGUSR2:
 166  		return "user defined signal 2"
 167  	case SIGPIPE:
 168  		return "broken pipe"
 169  	case SIGALRM:
 170  		return "alarm clock"
 171  	case SIGTERM:
 172  		return "terminated"
 173  	case SIGCHLD:
 174  		return "child exited"
 175  	case SIGCONT:
 176  		return "continued"
 177  	case SIGSTOP:
 178  		return "stopped (signal)"
 179  	case SIGTSTP:
 180  		return "stopped"
 181  	case SIGTTIN:
 182  		return "stopped (tty input)"
 183  	case SIGTTOU:
 184  		return "stopped (tty output)"
 185  	case SIGURG:
 186  		return "urgent I/O condition"
 187  	case SIGXCPU:
 188  		return "CPU time limit exceeded"
 189  	case SIGXFSZ:
 190  		return "file size limit exceeded"
 191  	case SIGVTARLM:
 192  		return "virtual timer expired"
 193  	case SIGPROF:
 194  		return "profiling timer expired"
 195  	case SIGWINCH:
 196  		return "window changed"
 197  	case SIGPOLL:
 198  		return "I/O possible"
 199  	case SIGPWR:
 200  		return "power failure"
 201  	case SIGSYS:
 202  		return "bad system call"
 203  	default:
 204  		return "signal " + itoa.Itoa(int(s))
 205  	}
 206  }
 207  
 208  const (
 209  	Stdin  = 0
 210  	Stdout = 1
 211  	Stderr = 2
 212  )
 213  
 214  const (
 215  	O_RDONLY = 0
 216  	O_WRONLY = 1
 217  	O_RDWR   = 2
 218  
 219  	O_CREAT     = 0100
 220  	O_CREATE    = O_CREAT
 221  	O_TRUNC     = 01000
 222  	O_APPEND    = 02000
 223  	O_EXCL      = 0200
 224  	O_SYNC      = 010000
 225  	O_DIRECTORY = 020000
 226  	O_NOFOLLOW  = 0400
 227  
 228  	O_CLOEXEC = 0
 229  )
 230  
 231  const (
 232  	F_DUPFD   = 0
 233  	F_GETFD   = 1
 234  	F_SETFD   = 2
 235  	F_GETFL   = 3
 236  	F_SETFL   = 4
 237  	F_GETOWN  = 5
 238  	F_SETOWN  = 6
 239  	F_GETLK   = 7
 240  	F_SETLK   = 8
 241  	F_SETLKW  = 9
 242  	F_RGETLK  = 10
 243  	F_RSETLK  = 11
 244  	F_CNVT    = 12
 245  	F_RSETLKW = 13
 246  
 247  	F_RDLCK   = 1
 248  	F_WRLCK   = 2
 249  	F_UNLCK   = 3
 250  	F_UNLKSYS = 4
 251  )
 252  
 253  const (
 254  	S_IFMT        = 0000370000
 255  	S_IFSHM_SYSV  = 0000300000
 256  	S_IFSEMA      = 0000270000
 257  	S_IFCOND      = 0000260000
 258  	S_IFMUTEX     = 0000250000
 259  	S_IFSHM       = 0000240000
 260  	S_IFBOUNDSOCK = 0000230000
 261  	S_IFSOCKADDR  = 0000220000
 262  	S_IFDSOCK     = 0000210000
 263  
 264  	S_IFSOCK = 0000140000
 265  	S_IFLNK  = 0000120000
 266  	S_IFREG  = 0000100000
 267  	S_IFBLK  = 0000060000
 268  	S_IFDIR  = 0000040000
 269  	S_IFCHR  = 0000020000
 270  	S_IFIFO  = 0000010000
 271  
 272  	S_UNSUP = 0000370000
 273  
 274  	S_ISUID = 0004000
 275  	S_ISGID = 0002000
 276  	S_ISVTX = 0001000
 277  
 278  	S_IREAD  = 0400
 279  	S_IWRITE = 0200
 280  	S_IEXEC  = 0100
 281  
 282  	S_IRWXU = 0700
 283  	S_IRUSR = 0400
 284  	S_IWUSR = 0200
 285  	S_IXUSR = 0100
 286  
 287  	S_IRWXG = 070
 288  	S_IRGRP = 040
 289  	S_IWGRP = 020
 290  	S_IXGRP = 010
 291  
 292  	S_IRWXO = 07
 293  	S_IROTH = 04
 294  	S_IWOTH = 02
 295  	S_IXOTH = 01
 296  )
 297  
 298  type WaitStatus uint32
 299  
 300  func (w WaitStatus) Exited() bool       { return false }
 301  func (w WaitStatus) ExitStatus() int    { return 0 }
 302  func (w WaitStatus) Signaled() bool     { return false }
 303  func (w WaitStatus) Signal() Signal     { return 0 }
 304  func (w WaitStatus) CoreDump() bool     { return false }
 305  func (w WaitStatus) Stopped() bool      { return false }
 306  func (w WaitStatus) Continued() bool    { return false }
 307  func (w WaitStatus) StopSignal() Signal { return 0 }
 308  func (w WaitStatus) TrapCause() int     { return 0 }
 309  
 310  // Rusage is a placeholder to allow compilation of the [os/exec] package
 311  // because we need Go programs to be portable across platforms. WASI does
 312  // not have a mechanism to spawn processes so there is no reason for an
 313  // application to take a dependency on this type.
 314  type Rusage struct {
 315  	Utime Timeval
 316  	Stime Timeval
 317  }
 318  
 319  // ProcAttr is a placeholder to allow compilation of the [os/exec] package
 320  // because we need Go programs to be portable across platforms. WASI does
 321  // not have a mechanism to spawn processes so there is no reason for an
 322  // application to take a dependency on this type.
 323  type ProcAttr struct {
 324  	Dir   string
 325  	Env   []string
 326  	Files []uintptr
 327  	Sys   *SysProcAttr
 328  }
 329  
 330  type SysProcAttr struct {
 331  }
 332  
 333  func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
 334  	return 0, 0, ENOSYS
 335  }
 336  
 337  func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
 338  	return 0, 0, ENOSYS
 339  }
 340  
 341  func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
 342  	return 0, 0, ENOSYS
 343  }
 344  
 345  func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
 346  	return 0, 0, ENOSYS
 347  }
 348  
 349  func Sysctl(key string) (string, error) {
 350  	if key == "kern.hostname" {
 351  		return "wasip1", nil
 352  	}
 353  	return "", ENOSYS
 354  }
 355  
 356  func Getuid() int {
 357  	return 1
 358  }
 359  
 360  func Getgid() int {
 361  	return 1
 362  }
 363  
 364  func Geteuid() int {
 365  	return 1
 366  }
 367  
 368  func Getegid() int {
 369  	return 1
 370  }
 371  
 372  func Getgroups() ([]int, error) {
 373  	return []int{1}, nil
 374  }
 375  
 376  func Getpid() int {
 377  	return 3
 378  }
 379  
 380  func Getppid() int {
 381  	return 2
 382  }
 383  
 384  func Gettimeofday(tv *Timeval) error {
 385  	var time timestamp
 386  	if errno := clock_time_get(clockRealtime, 1e3, &time); errno != 0 {
 387  		return errno
 388  	}
 389  	tv.setTimestamp(time)
 390  	return nil
 391  }
 392  
 393  func Kill(pid int, signum Signal) error {
 394  	// WASI does not have the notion of processes nor signal handlers.
 395  	//
 396  	// Any signal that the application raises to the process itself will
 397  	// be interpreted as being cause for termination.
 398  	if pid > 0 && pid != Getpid() {
 399  		return ESRCH
 400  	}
 401  	ProcExit(128 + int32(signum))
 402  	return nil
 403  }
 404  
 405  func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 406  	return 0, ENOSYS
 407  }
 408  
 409  func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {
 410  	return 0, 0, ENOSYS
 411  }
 412  
 413  func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
 414  	return 0, ENOSYS
 415  }
 416  
 417  func Umask(mask int) int {
 418  	return 0
 419  }
 420  
 421  type Timespec struct {
 422  	Sec  int64
 423  	Nsec int64
 424  }
 425  
 426  func (ts *Timespec) timestamp() timestamp {
 427  	return timestamp(ts.Sec*1e9) + timestamp(ts.Nsec)
 428  }
 429  
 430  func (ts *Timespec) setTimestamp(t timestamp) {
 431  	ts.Sec = int64(t / 1e9)
 432  	ts.Nsec = int64(t % 1e9)
 433  }
 434  
 435  type Timeval struct {
 436  	Sec  int64
 437  	Usec int64
 438  }
 439  
 440  func (tv *Timeval) timestamp() timestamp {
 441  	return timestamp(tv.Sec*1e9) + timestamp(tv.Usec*1e3)
 442  }
 443  
 444  func (tv *Timeval) setTimestamp(t timestamp) {
 445  	tv.Sec = int64(t / 1e9)
 446  	tv.Usec = int64((t % 1e9) / 1e3)
 447  }
 448  
 449  func setTimespec(sec, nsec int64) Timespec {
 450  	return Timespec{Sec: sec, Nsec: nsec}
 451  }
 452  
 453  func setTimeval(sec, usec int64) Timeval {
 454  	return Timeval{Sec: sec, Usec: usec}
 455  }
 456  
 457  type clockid = uint32
 458  
 459  const (
 460  	clockRealtime clockid = iota
 461  	clockMonotonic
 462  	clockProcessCPUTimeID
 463  	clockThreadCPUTimeID
 464  )
 465  
 466  //go:wasmimport wasi_snapshot_preview1 clock_time_get
 467  //go:noescape
 468  func clock_time_get(id clockid, precision timestamp, time *timestamp) Errno
 469  
 470  func SetNonblock(fd int, nonblocking bool) error {
 471  	flags, err := fd_fdstat_get_flags(fd)
 472  	if err != nil {
 473  		return err
 474  	}
 475  	if nonblocking {
 476  		flags |= FDFLAG_NONBLOCK
 477  	} else {
 478  		flags &^= FDFLAG_NONBLOCK
 479  	}
 480  	errno := fd_fdstat_set_flags(int32(fd), flags)
 481  	return errnoErr(errno)
 482  }
 483  
 484  type Rlimit struct {
 485  	Cur uint64
 486  	Max uint64
 487  }
 488  
 489  const (
 490  	RLIMIT_NOFILE = iota
 491  )
 492  
 493  func Getrlimit(which int, lim *Rlimit) error {
 494  	return ENOSYS
 495  }
 496