Source file src/syscall/syscall_wasip1.go

     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  
   226  	O_CLOEXEC = 0
   227  )
   228  
   229  const (
   230  	F_DUPFD   = 0
   231  	F_GETFD   = 1
   232  	F_SETFD   = 2
   233  	F_GETFL   = 3
   234  	F_SETFL   = 4
   235  	F_GETOWN  = 5
   236  	F_SETOWN  = 6
   237  	F_GETLK   = 7
   238  	F_SETLK   = 8
   239  	F_SETLKW  = 9
   240  	F_RGETLK  = 10
   241  	F_RSETLK  = 11
   242  	F_CNVT    = 12
   243  	F_RSETLKW = 13
   244  
   245  	F_RDLCK   = 1
   246  	F_WRLCK   = 2
   247  	F_UNLCK   = 3
   248  	F_UNLKSYS = 4
   249  )
   250  
   251  const (
   252  	S_IFMT        = 0000370000
   253  	S_IFSHM_SYSV  = 0000300000
   254  	S_IFSEMA      = 0000270000
   255  	S_IFCOND      = 0000260000
   256  	S_IFMUTEX     = 0000250000
   257  	S_IFSHM       = 0000240000
   258  	S_IFBOUNDSOCK = 0000230000
   259  	S_IFSOCKADDR  = 0000220000
   260  	S_IFDSOCK     = 0000210000
   261  
   262  	S_IFSOCK = 0000140000
   263  	S_IFLNK  = 0000120000
   264  	S_IFREG  = 0000100000
   265  	S_IFBLK  = 0000060000
   266  	S_IFDIR  = 0000040000
   267  	S_IFCHR  = 0000020000
   268  	S_IFIFO  = 0000010000
   269  
   270  	S_UNSUP = 0000370000
   271  
   272  	S_ISUID = 0004000
   273  	S_ISGID = 0002000
   274  	S_ISVTX = 0001000
   275  
   276  	S_IREAD  = 0400
   277  	S_IWRITE = 0200
   278  	S_IEXEC  = 0100
   279  
   280  	S_IRWXU = 0700
   281  	S_IRUSR = 0400
   282  	S_IWUSR = 0200
   283  	S_IXUSR = 0100
   284  
   285  	S_IRWXG = 070
   286  	S_IRGRP = 040
   287  	S_IWGRP = 020
   288  	S_IXGRP = 010
   289  
   290  	S_IRWXO = 07
   291  	S_IROTH = 04
   292  	S_IWOTH = 02
   293  	S_IXOTH = 01
   294  )
   295  
   296  type WaitStatus uint32
   297  
   298  func (w WaitStatus) Exited() bool       { return false }
   299  func (w WaitStatus) ExitStatus() int    { return 0 }
   300  func (w WaitStatus) Signaled() bool     { return false }
   301  func (w WaitStatus) Signal() Signal     { return 0 }
   302  func (w WaitStatus) CoreDump() bool     { return false }
   303  func (w WaitStatus) Stopped() bool      { return false }
   304  func (w WaitStatus) Continued() bool    { return false }
   305  func (w WaitStatus) StopSignal() Signal { return 0 }
   306  func (w WaitStatus) TrapCause() int     { return 0 }
   307  
   308  // Rusage is a placeholder to allow compilation of the [os/exec] package
   309  // because we need Go programs to be portable across platforms. WASI does
   310  // not have a mechanism to to spawn processes so there is no reason for an
   311  // application to take a dependency on this type.
   312  type Rusage struct {
   313  	Utime Timeval
   314  	Stime Timeval
   315  }
   316  
   317  // ProcAttr is a placeholder to allow compilation of the [os/exec] package
   318  // because we need Go programs to be portable across platforms. WASI does
   319  // not have a mechanism to to spawn processes so there is no reason for an
   320  // application to take a dependency on this type.
   321  type ProcAttr struct {
   322  	Dir   string
   323  	Env   []string
   324  	Files []uintptr
   325  	Sys   *SysProcAttr
   326  }
   327  
   328  type SysProcAttr struct {
   329  }
   330  
   331  func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
   332  	return 0, 0, ENOSYS
   333  }
   334  
   335  func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
   336  	return 0, 0, ENOSYS
   337  }
   338  
   339  func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
   340  	return 0, 0, ENOSYS
   341  }
   342  
   343  func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
   344  	return 0, 0, ENOSYS
   345  }
   346  
   347  func Sysctl(key string) (string, error) {
   348  	if key == "kern.hostname" {
   349  		return "wasip1", nil
   350  	}
   351  	return "", ENOSYS
   352  }
   353  
   354  func Getuid() int {
   355  	return 1
   356  }
   357  
   358  func Getgid() int {
   359  	return 1
   360  }
   361  
   362  func Geteuid() int {
   363  	return 1
   364  }
   365  
   366  func Getegid() int {
   367  	return 1
   368  }
   369  
   370  func Getgroups() ([]int, error) {
   371  	return []int{1}, nil
   372  }
   373  
   374  func Getpid() int {
   375  	return 3
   376  }
   377  
   378  func Getppid() int {
   379  	return 2
   380  }
   381  
   382  func Gettimeofday(tv *Timeval) error {
   383  	var time timestamp
   384  	if errno := clock_time_get(clockRealtime, 1e3, unsafe.Pointer(&time)); errno != 0 {
   385  		return errno
   386  	}
   387  	tv.setTimestamp(time)
   388  	return nil
   389  }
   390  
   391  func Kill(pid int, signum Signal) error {
   392  	// WASI does not have the notion of processes nor signal handlers.
   393  	//
   394  	// Any signal that the application raises to the process itself will
   395  	// be interpreted as being cause for termination.
   396  	if pid > 0 && pid != Getpid() {
   397  		return ESRCH
   398  	}
   399  	ProcExit(128 + int32(signum))
   400  	return nil
   401  }
   402  
   403  func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
   404  	return 0, ENOSYS
   405  }
   406  
   407  func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {
   408  	return 0, 0, ENOSYS
   409  }
   410  
   411  func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
   412  	return 0, ENOSYS
   413  }
   414  
   415  func Umask(mask int) int {
   416  	return 0
   417  }
   418  
   419  type Timespec struct {
   420  	Sec  int64
   421  	Nsec int64
   422  }
   423  
   424  func (ts *Timespec) timestamp() timestamp {
   425  	return timestamp(ts.Sec*1e9) + timestamp(ts.Nsec)
   426  }
   427  
   428  func (ts *Timespec) setTimestamp(t timestamp) {
   429  	ts.Sec = int64(t / 1e9)
   430  	ts.Nsec = int64(t % 1e9)
   431  }
   432  
   433  type Timeval struct {
   434  	Sec  int64
   435  	Usec int64
   436  }
   437  
   438  func (tv *Timeval) timestamp() timestamp {
   439  	return timestamp(tv.Sec*1e9) + timestamp(tv.Usec*1e3)
   440  }
   441  
   442  func (tv *Timeval) setTimestamp(t timestamp) {
   443  	tv.Sec = int64(t / 1e9)
   444  	tv.Usec = int64((t % 1e9) / 1e3)
   445  }
   446  
   447  func setTimespec(sec, nsec int64) Timespec {
   448  	return Timespec{Sec: sec, Nsec: nsec}
   449  }
   450  
   451  func setTimeval(sec, usec int64) Timeval {
   452  	return Timeval{Sec: sec, Usec: usec}
   453  }
   454  
   455  type clockid = uint32
   456  
   457  const (
   458  	clockRealtime clockid = iota
   459  	clockMonotonic
   460  	clockProcessCPUTimeID
   461  	clockThreadCPUTimeID
   462  )
   463  
   464  //go:wasmimport wasi_snapshot_preview1 clock_time_get
   465  //go:noescape
   466  func clock_time_get(id clockid, precision timestamp, time unsafe.Pointer) Errno
   467  
   468  func SetNonblock(fd int, nonblocking bool) error {
   469  	flags, err := fd_fdstat_get_flags(fd)
   470  	if err != nil {
   471  		return err
   472  	}
   473  	if nonblocking {
   474  		flags |= FDFLAG_NONBLOCK
   475  	} else {
   476  		flags &^= FDFLAG_NONBLOCK
   477  	}
   478  	errno := fd_fdstat_set_flags(int32(fd), flags)
   479  	return errnoErr(errno)
   480  }
   481  
   482  type Rlimit struct {
   483  	Cur uint64
   484  	Max uint64
   485  }
   486  
   487  const (
   488  	RLIMIT_NOFILE = iota
   489  )
   490  
   491  func Getrlimit(which int, lim *Rlimit) error {
   492  	return ENOSYS
   493  }
   494  

View as plain text