blob: 84e14714811d3cdf82fe7d05f6de53f7c7e53c8c [file] [log] [blame]
David K. Bainbridgebd6b2882021-08-26 13:31:02 +00001// Copyright 2011 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// Plan 9 system calls.
6// This file is compiled as ordinary Go code,
7// but it is also input to mksyscall,
8// which parses the //sys lines and generates system call stubs.
9// Note that sometimes we use a lowercase //sys name and
10// wrap it in our own nicer implementation.
11
12package plan9
13
14import (
15 "bytes"
16 "syscall"
17 "unsafe"
18)
19
20// A Note is a string describing a process note.
21// It implements the os.Signal interface.
22type Note string
23
24func (n Note) Signal() {}
25
26func (n Note) String() string {
27 return string(n)
28}
29
30var (
31 Stdin = 0
32 Stdout = 1
33 Stderr = 2
34)
35
36// For testing: clients can set this flag to force
37// creation of IPv6 sockets to return EAFNOSUPPORT.
38var SocketDisableIPv6 bool
39
40func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.ErrorString)
41func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.ErrorString)
42func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
43func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
44
45func atoi(b []byte) (n uint) {
46 n = 0
47 for i := 0; i < len(b); i++ {
48 n = n*10 + uint(b[i]-'0')
49 }
50 return
51}
52
53func cstring(s []byte) string {
54 i := bytes.IndexByte(s, 0)
55 if i == -1 {
56 i = len(s)
57 }
58 return string(s[:i])
59}
60
61func errstr() string {
62 var buf [ERRMAX]byte
63
64 RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)
65
66 buf[len(buf)-1] = 0
67 return cstring(buf[:])
68}
69
70// Implemented in assembly to import from runtime.
71func exit(code int)
72
73func Exit(code int) { exit(code) }
74
75func readnum(path string) (uint, error) {
76 var b [12]byte
77
78 fd, e := Open(path, O_RDONLY)
79 if e != nil {
80 return 0, e
81 }
82 defer Close(fd)
83
84 n, e := Pread(fd, b[:], 0)
85
86 if e != nil {
87 return 0, e
88 }
89
90 m := 0
91 for ; m < n && b[m] == ' '; m++ {
92 }
93
94 return atoi(b[m : n-1]), nil
95}
96
97func Getpid() (pid int) {
98 n, _ := readnum("#c/pid")
99 return int(n)
100}
101
102func Getppid() (ppid int) {
103 n, _ := readnum("#c/ppid")
104 return int(n)
105}
106
107func Read(fd int, p []byte) (n int, err error) {
108 return Pread(fd, p, -1)
109}
110
111func Write(fd int, p []byte) (n int, err error) {
112 return Pwrite(fd, p, -1)
113}
114
115var ioSync int64
116
117//sys fd2path(fd int, buf []byte) (err error)
118func Fd2path(fd int) (path string, err error) {
119 var buf [512]byte
120
121 e := fd2path(fd, buf[:])
122 if e != nil {
123 return "", e
124 }
125 return cstring(buf[:]), nil
126}
127
128//sys pipe(p *[2]int32) (err error)
129func Pipe(p []int) (err error) {
130 if len(p) != 2 {
131 return syscall.ErrorString("bad arg in system call")
132 }
133 var pp [2]int32
134 err = pipe(&pp)
135 p[0] = int(pp[0])
136 p[1] = int(pp[1])
137 return
138}
139
140// Underlying system call writes to newoffset via pointer.
141// Implemented in assembly to avoid allocation.
142func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
143
144func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
145 newoffset, e := seek(0, fd, offset, whence)
146
147 if newoffset == -1 {
148 err = syscall.ErrorString(e)
149 }
150 return
151}
152
153func Mkdir(path string, mode uint32) (err error) {
154 fd, err := Create(path, O_RDONLY, DMDIR|mode)
155
156 if fd != -1 {
157 Close(fd)
158 }
159
160 return
161}
162
163type Waitmsg struct {
164 Pid int
165 Time [3]uint32
166 Msg string
167}
168
169func (w Waitmsg) Exited() bool { return true }
170func (w Waitmsg) Signaled() bool { return false }
171
172func (w Waitmsg) ExitStatus() int {
173 if len(w.Msg) == 0 {
174 // a normal exit returns no message
175 return 0
176 }
177 return 1
178}
179
180//sys await(s []byte) (n int, err error)
181func Await(w *Waitmsg) (err error) {
182 var buf [512]byte
183 var f [5][]byte
184
185 n, err := await(buf[:])
186
187 if err != nil || w == nil {
188 return
189 }
190
191 nf := 0
192 p := 0
193 for i := 0; i < n && nf < len(f)-1; i++ {
194 if buf[i] == ' ' {
195 f[nf] = buf[p:i]
196 p = i + 1
197 nf++
198 }
199 }
200 f[nf] = buf[p:]
201 nf++
202
203 if nf != len(f) {
204 return syscall.ErrorString("invalid wait message")
205 }
206 w.Pid = int(atoi(f[0]))
207 w.Time[0] = uint32(atoi(f[1]))
208 w.Time[1] = uint32(atoi(f[2]))
209 w.Time[2] = uint32(atoi(f[3]))
210 w.Msg = cstring(f[4])
211 if w.Msg == "''" {
212 // await() returns '' for no error
213 w.Msg = ""
214 }
215 return
216}
217
218func Unmount(name, old string) (err error) {
219 fixwd()
220 oldp, err := BytePtrFromString(old)
221 if err != nil {
222 return err
223 }
224 oldptr := uintptr(unsafe.Pointer(oldp))
225
226 var r0 uintptr
227 var e syscall.ErrorString
228
229 // bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
230 if name == "" {
231 r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldptr, 0)
232 } else {
233 namep, err := BytePtrFromString(name)
234 if err != nil {
235 return err
236 }
237 r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0)
238 }
239
240 if int32(r0) == -1 {
241 err = e
242 }
243 return
244}
245
246func Fchdir(fd int) (err error) {
247 path, err := Fd2path(fd)
248
249 if err != nil {
250 return
251 }
252
253 return Chdir(path)
254}
255
256type Timespec struct {
257 Sec int32
258 Nsec int32
259}
260
261type Timeval struct {
262 Sec int32
263 Usec int32
264}
265
266func NsecToTimeval(nsec int64) (tv Timeval) {
267 nsec += 999 // round up to microsecond
268 tv.Usec = int32(nsec % 1e9 / 1e3)
269 tv.Sec = int32(nsec / 1e9)
270 return
271}
272
273func nsec() int64 {
274 var scratch int64
275
276 r0, _, _ := Syscall(SYS_NSEC, uintptr(unsafe.Pointer(&scratch)), 0, 0)
277 // TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
278 if r0 == 0 {
279 return scratch
280 }
281 return int64(r0)
282}
283
284func Gettimeofday(tv *Timeval) error {
285 nsec := nsec()
286 *tv = NsecToTimeval(nsec)
287 return nil
288}
289
290func Getpagesize() int { return 0x1000 }
291
292func Getegid() (egid int) { return -1 }
293func Geteuid() (euid int) { return -1 }
294func Getgid() (gid int) { return -1 }
295func Getuid() (uid int) { return -1 }
296
297func Getgroups() (gids []int, err error) {
298 return make([]int, 0), nil
299}
300
301//sys open(path string, mode int) (fd int, err error)
302func Open(path string, mode int) (fd int, err error) {
303 fixwd()
304 return open(path, mode)
305}
306
307//sys create(path string, mode int, perm uint32) (fd int, err error)
308func Create(path string, mode int, perm uint32) (fd int, err error) {
309 fixwd()
310 return create(path, mode, perm)
311}
312
313//sys remove(path string) (err error)
314func Remove(path string) error {
315 fixwd()
316 return remove(path)
317}
318
319//sys stat(path string, edir []byte) (n int, err error)
320func Stat(path string, edir []byte) (n int, err error) {
321 fixwd()
322 return stat(path, edir)
323}
324
325//sys bind(name string, old string, flag int) (err error)
326func Bind(name string, old string, flag int) (err error) {
327 fixwd()
328 return bind(name, old, flag)
329}
330
331//sys mount(fd int, afd int, old string, flag int, aname string) (err error)
332func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
333 fixwd()
334 return mount(fd, afd, old, flag, aname)
335}
336
337//sys wstat(path string, edir []byte) (err error)
338func Wstat(path string, edir []byte) (err error) {
339 fixwd()
340 return wstat(path, edir)
341}
342
343//sys chdir(path string) (err error)
344//sys Dup(oldfd int, newfd int) (fd int, err error)
345//sys Pread(fd int, p []byte, offset int64) (n int, err error)
346//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
347//sys Close(fd int) (err error)
348//sys Fstat(fd int, edir []byte) (n int, err error)
349//sys Fwstat(fd int, edir []byte) (err error)