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  	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  

View as plain text