syscall_js.mx raw

   1  // Copyright 2018 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 js && wasm
   6  
   7  package syscall
   8  
   9  import (
  10  	errorspkg "errors"
  11  	"internal/itoa"
  12  	"internal/oserror"
  13  	"sync"
  14  	"unsafe"
  15  )
  16  
  17  const direntSize = 8 + 8 + 2 + 256
  18  
  19  type Dirent struct {
  20  	Reclen uint16
  21  	Name   [256]byte
  22  }
  23  
  24  func direntIno(buf []byte) (uint64, bool) {
  25  	return 1, true
  26  }
  27  
  28  func direntReclen(buf []byte) (uint64, bool) {
  29  	return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
  30  }
  31  
  32  func direntNamlen(buf []byte) (uint64, bool) {
  33  	reclen, ok := direntReclen(buf)
  34  	if !ok {
  35  		return 0, false
  36  	}
  37  	return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
  38  }
  39  
  40  const PathMax = 256
  41  
  42  // An Errno is an unsigned number describing an error condition.
  43  // It implements the error interface. The zero Errno is by convention
  44  // a non-error, so code to convert from Errno to error should use:
  45  //
  46  //	err = nil
  47  //	if errno != 0 {
  48  //		err = errno
  49  //	}
  50  //
  51  // Errno values can be tested against error values using [errors.Is].
  52  // For example:
  53  //
  54  //	_, _, err := syscall.Syscall(...)
  55  //	if errors.Is(err, fs.ErrNotExist) ...
  56  type Errno uintptr
  57  
  58  func (e Errno) Error() string {
  59  	if 0 <= int(e) && int(e) < len(errorstr) {
  60  		s := errorstr[e]
  61  		if s != "" {
  62  			return s
  63  		}
  64  	}
  65  	return "errno " + itoa.Itoa(int(e))
  66  }
  67  
  68  func (e Errno) Is(target error) bool {
  69  	switch target {
  70  	case oserror.ErrPermission:
  71  		return e == EACCES || e == EPERM
  72  	case oserror.ErrExist:
  73  		return e == EEXIST || e == ENOTEMPTY
  74  	case oserror.ErrNotExist:
  75  		return e == ENOENT
  76  	case errorspkg.ErrUnsupported:
  77  		return e == ENOSYS || e == ENOTSUP || e == EOPNOTSUPP
  78  	}
  79  	return false
  80  }
  81  
  82  func (e Errno) Temporary() bool {
  83  	return e == EINTR || e == EMFILE || e.Timeout()
  84  }
  85  
  86  func (e Errno) Timeout() bool {
  87  	return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
  88  }
  89  
  90  // A Signal is a number describing a process signal.
  91  // It implements the [os.Signal] interface.
  92  type Signal int
  93  
  94  const (
  95  	_ Signal = iota
  96  	SIGCHLD
  97  	SIGINT
  98  	SIGKILL
  99  	SIGTRAP
 100  	SIGQUIT
 101  	SIGTERM
 102  )
 103  
 104  func (s Signal) Signal() {}
 105  
 106  func (s Signal) String() string {
 107  	if 0 <= s && int(s) < len(signals) {
 108  		str := signals[s]
 109  		if str != "" {
 110  			return str
 111  		}
 112  	}
 113  	return "signal " + itoa.Itoa(int(s))
 114  }
 115  
 116  var signals = [...]string{}
 117  
 118  // File system
 119  
 120  const (
 121  	Stdin  = 0
 122  	Stdout = 1
 123  	Stderr = 2
 124  )
 125  
 126  const (
 127  	O_RDONLY = 0
 128  	O_WRONLY = 1
 129  	O_RDWR   = 2
 130  
 131  	O_CREAT     = 0100
 132  	O_CREATE    = O_CREAT
 133  	O_TRUNC     = 01000
 134  	O_APPEND    = 02000
 135  	O_EXCL      = 0200
 136  	O_SYNC      = 010000
 137  	O_DIRECTORY = 020000
 138  
 139  	O_CLOEXEC = 0
 140  )
 141  
 142  const (
 143  	F_DUPFD   = 0
 144  	F_GETFD   = 1
 145  	F_SETFD   = 2
 146  	F_GETFL   = 3
 147  	F_SETFL   = 4
 148  	F_GETOWN  = 5
 149  	F_SETOWN  = 6
 150  	F_GETLK   = 7
 151  	F_SETLK   = 8
 152  	F_SETLKW  = 9
 153  	F_RGETLK  = 10
 154  	F_RSETLK  = 11
 155  	F_CNVT    = 12
 156  	F_RSETLKW = 13
 157  
 158  	F_RDLCK   = 1
 159  	F_WRLCK   = 2
 160  	F_UNLCK   = 3
 161  	F_UNLKSYS = 4
 162  )
 163  
 164  const (
 165  	S_IFMT        = 0000370000
 166  	S_IFSHM_SYSV  = 0000300000
 167  	S_IFSEMA      = 0000270000
 168  	S_IFCOND      = 0000260000
 169  	S_IFMUTEX     = 0000250000
 170  	S_IFSHM       = 0000240000
 171  	S_IFBOUNDSOCK = 0000230000
 172  	S_IFSOCKADDR  = 0000220000
 173  	S_IFDSOCK     = 0000210000
 174  
 175  	S_IFSOCK = 0000140000
 176  	S_IFLNK  = 0000120000
 177  	S_IFREG  = 0000100000
 178  	S_IFBLK  = 0000060000
 179  	S_IFDIR  = 0000040000
 180  	S_IFCHR  = 0000020000
 181  	S_IFIFO  = 0000010000
 182  
 183  	S_UNSUP = 0000370000
 184  
 185  	S_ISUID = 0004000
 186  	S_ISGID = 0002000
 187  	S_ISVTX = 0001000
 188  
 189  	S_IREAD  = 0400
 190  	S_IWRITE = 0200
 191  	S_IEXEC  = 0100
 192  
 193  	S_IRWXU = 0700
 194  	S_IRUSR = 0400
 195  	S_IWUSR = 0200
 196  	S_IXUSR = 0100
 197  
 198  	S_IRWXG = 070
 199  	S_IRGRP = 040
 200  	S_IWGRP = 020
 201  	S_IXGRP = 010
 202  
 203  	S_IRWXO = 07
 204  	S_IROTH = 04
 205  	S_IWOTH = 02
 206  	S_IXOTH = 01
 207  )
 208  
 209  type Stat_t struct {
 210  	Dev       int64
 211  	Ino       uint64
 212  	Mode      uint32
 213  	Nlink     uint32
 214  	Uid       uint32
 215  	Gid       uint32
 216  	Rdev      int64
 217  	Size      int64
 218  	Blksize   int32
 219  	Blocks    int32
 220  	Atime     int64
 221  	AtimeNsec int64
 222  	Mtime     int64
 223  	MtimeNsec int64
 224  	Ctime     int64
 225  	CtimeNsec int64
 226  }
 227  
 228  // Processes
 229  // Not supported - just enough for package os.
 230  
 231  var ForkLock sync.RWMutex
 232  
 233  type WaitStatus uint32
 234  
 235  func (w WaitStatus) Exited() bool       { return false }
 236  func (w WaitStatus) ExitStatus() int    { return 0 }
 237  func (w WaitStatus) Signaled() bool     { return false }
 238  func (w WaitStatus) Signal() Signal     { return 0 }
 239  func (w WaitStatus) CoreDump() bool     { return false }
 240  func (w WaitStatus) Stopped() bool      { return false }
 241  func (w WaitStatus) Continued() bool    { return false }
 242  func (w WaitStatus) StopSignal() Signal { return 0 }
 243  func (w WaitStatus) TrapCause() int     { return 0 }
 244  
 245  // XXX made up
 246  type Rusage struct {
 247  	Utime Timeval
 248  	Stime Timeval
 249  }
 250  
 251  // XXX made up
 252  type ProcAttr struct {
 253  	Dir   string
 254  	Env   []string
 255  	Files []uintptr
 256  	Sys   *SysProcAttr
 257  }
 258  
 259  type SysProcAttr struct {
 260  }
 261  
 262  func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
 263  	return 0, 0, ENOSYS
 264  }
 265  
 266  func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
 267  	return 0, 0, ENOSYS
 268  }
 269  
 270  func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
 271  	return 0, 0, ENOSYS
 272  }
 273  
 274  func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
 275  	return 0, 0, ENOSYS
 276  }
 277  
 278  func Sysctl(key string) (string, error) {
 279  	if key == "kern.hostname" {
 280  		return "js", nil
 281  	}
 282  	return "", ENOSYS
 283  }
 284  
 285  const ImplementsGetwd = true
 286  
 287  func Getwd() (wd string, err error) {
 288  	var buf [PathMax]byte
 289  	n, err := Getcwd(buf[0:])
 290  	if err != nil {
 291  		return "", err
 292  	}
 293  	return string(buf[:n]), nil
 294  }
 295  
 296  func Getuid() int {
 297  	return jsProcess.Call("getuid").Int()
 298  }
 299  
 300  func Getgid() int {
 301  	return jsProcess.Call("getgid").Int()
 302  }
 303  
 304  func Geteuid() int {
 305  	return jsProcess.Call("geteuid").Int()
 306  }
 307  
 308  func Getegid() int {
 309  	return jsProcess.Call("getegid").Int()
 310  }
 311  
 312  func Getgroups() (groups []int, err error) {
 313  	defer recoverErr(&err)
 314  	array := jsProcess.Call("getgroups")
 315  	groups = make([]int, array.Length())
 316  	for i := range groups {
 317  		groups[i] = array.Index(i).Int()
 318  	}
 319  	return groups, nil
 320  }
 321  
 322  func Getpid() int {
 323  	return jsProcess.Get("pid").Int()
 324  }
 325  
 326  func Getppid() int {
 327  	return jsProcess.Get("ppid").Int()
 328  }
 329  
 330  func Umask(mask int) (oldmask int) {
 331  	return jsProcess.Call("umask", mask).Int()
 332  }
 333  
 334  func Gettimeofday(tv *Timeval) error { return ENOSYS }
 335  
 336  func Kill(pid int, signum Signal) error { return ENOSYS }
 337  func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 338  	return 0, ENOSYS
 339  }
 340  func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {
 341  	return 0, 0, ENOSYS
 342  }
 343  func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
 344  	return 0, ENOSYS
 345  }
 346  
 347  type Iovec struct{} // dummy
 348  
 349  type Timespec struct {
 350  	Sec  int64
 351  	Nsec int64
 352  }
 353  
 354  type Timeval struct {
 355  	Sec  int64
 356  	Usec int64
 357  }
 358  
 359  func setTimespec(sec, nsec int64) Timespec {
 360  	return Timespec{Sec: sec, Nsec: nsec}
 361  }
 362  
 363  func setTimeval(sec, usec int64) Timeval {
 364  	return Timeval{Sec: sec, Usec: usec}
 365  }
 366