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