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