blob: b511867cda51d4cd13dee6ca7f4adabf8d048c32 [file] [log] [blame]
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -07001// 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 syscall
13
14import "unsafe"
15
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070016const ImplementsGetwd = true
17
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070018// ErrorString implements Error's String method by returning itself.
19type ErrorString string
20
Anthony Martincabe0e62011-11-08 09:06:02 -050021func (e ErrorString) Error() string { return string(e) }
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070022
23// NewError converts s to an ErrorString, which satisfies the Error interface.
Lucio De Re087a3482011-11-16 17:37:54 -050024func NewError(s string) error { return ErrorString(s) }
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070025
Akshat Kumarf0a8b612013-02-28 06:43:21 +010026func (e ErrorString) Temporary() bool {
27 return e == EINTR || e == EMFILE || e.Timeout()
28}
29
30func (e ErrorString) Timeout() bool {
31 return e == EBUSY || e == ETIMEDOUT
32}
33
Anthony Martinfe5005f2012-05-04 03:44:41 -070034// A Note is a string describing a process note.
35// It implements the os.Signal interface.
36type Note string
37
38func (n Note) Signal() {}
39
40func (n Note) String() string {
41 return string(n)
42}
43
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070044var (
45 Stdin = 0
46 Stdout = 1
47 Stderr = 2
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070048)
49
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040050// For testing: clients can set this flag to force
51// creation of IPv6 sockets to return EAFNOSUPPORT.
52var SocketDisableIPv6 bool
53
Lucio De Re8ec32e82011-11-21 09:55:15 -050054func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err ErrorString)
55func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err ErrorString)
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070056func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
57func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
58
Richard Miller639a20d2016-04-29 17:39:33 +010059//go:nosplit
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070060func atoi(b []byte) (n uint) {
61 n = 0
62 for i := 0; i < len(b); i++ {
63 n = n*10 + uint(b[i]-'0')
64 }
65 return
66}
67
68func cstring(s []byte) string {
Robert Griesemera2e28682011-04-13 15:13:59 -070069 for i := range s {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070070 if s[i] == 0 {
71 return string(s[0:i])
72 }
73 }
74 return string(s)
75}
76
77func errstr() string {
78 var buf [ERRMAX]byte
79
80 RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)
81
82 buf[len(buf)-1] = 0
83 return cstring(buf[:])
84}
85
Akshat Kumar49a7da22012-04-19 16:31:26 -070086// Implemented in assembly to import from runtime.
Russ Cox7ad60b72014-05-15 16:47:53 -040087func exit(code int)
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070088
Akshat Kumar49a7da22012-04-19 16:31:26 -070089func Exit(code int) { exit(code) }
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070090
Lucio De Re087a3482011-11-16 17:37:54 -050091func readnum(path string) (uint, error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070092 var b [12]byte
93
94 fd, e := Open(path, O_RDONLY)
95 if e != nil {
96 return 0, e
97 }
98 defer Close(fd)
99
100 n, e := Pread(fd, b[:], 0)
101
102 if e != nil {
103 return 0, e
104 }
105
106 m := 0
107 for ; m < n && b[m] == ' '; m++ {
108 }
109
110 return atoi(b[m : n-1]), nil
111}
112
113func Getpid() (pid int) {
114 n, _ := readnum("#c/pid")
115 return int(n)
116}
117
118func Getppid() (ppid int) {
119 n, _ := readnum("#c/ppid")
120 return int(n)
121}
122
Lucio De Re087a3482011-11-16 17:37:54 -0500123func Read(fd int, p []byte) (n int, err error) {
Dmitriy Vyukovfc807642013-06-10 22:40:35 +0400124 return Pread(fd, p, -1)
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700125}
126
Lucio De Re087a3482011-11-16 17:37:54 -0500127func Write(fd int, p []byte) (n int, err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700128 return Pwrite(fd, p, -1)
129}
130
Dmitriy Vyukovcffbfae2012-10-09 20:51:58 +0400131var ioSync int64
132
Lucio De Re087a3482011-11-16 17:37:54 -0500133//sys fd2path(fd int, buf []byte) (err error)
134func Fd2path(fd int) (path string, err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700135 var buf [512]byte
136
137 e := fd2path(fd, buf[:])
138 if e != nil {
139 return "", e
140 }
141 return cstring(buf[:]), nil
142}
143
Anthony Martinb9ba4ed2014-12-30 06:14:55 -0800144//sys pipe(p *[2]int32) (err error)
Lucio De Re087a3482011-11-16 17:37:54 -0500145func Pipe(p []int) (err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700146 if len(p) != 2 {
147 return NewError("bad arg in system call")
148 }
Anthony Martinb9ba4ed2014-12-30 06:14:55 -0800149 var pp [2]int32
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700150 err = pipe(&pp)
151 p[0] = int(pp[0])
152 p[1] = int(pp[1])
153 return
154}
155
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700156// Underlying system call writes to newoffset via pointer.
157// Implemented in assembly to avoid allocation.
158func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
159
Lucio De Re087a3482011-11-16 17:37:54 -0500160func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700161 newoffset, e := seek(0, fd, offset, whence)
162
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700163 if newoffset == -1 {
164 err = NewError(e)
165 }
166 return
167}
168
Lucio De Re087a3482011-11-16 17:37:54 -0500169func Mkdir(path string, mode uint32) (err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700170 fd, err := Create(path, O_RDONLY, DMDIR|mode)
171
172 if fd != -1 {
173 Close(fd)
174 }
175
176 return
177}
178
179type Waitmsg struct {
180 Pid int
181 Time [3]uint32
182 Msg string
183}
184
Anthony Martin20943ba2011-06-20 13:34:10 +1000185func (w Waitmsg) Exited() bool { return true }
186func (w Waitmsg) Signaled() bool { return false }
187
188func (w Waitmsg) ExitStatus() int {
189 if len(w.Msg) == 0 {
190 // a normal exit returns no message
191 return 0
192 }
193 return 1
194}
195
Lucio De Re087a3482011-11-16 17:37:54 -0500196//sys await(s []byte) (n int, err error)
197func Await(w *Waitmsg) (err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700198 var buf [512]byte
199 var f [5][]byte
200
201 n, err := await(buf[:])
202
203 if err != nil || w == nil {
204 return
205 }
206
207 nf := 0
208 p := 0
209 for i := 0; i < n && nf < len(f)-1; i++ {
210 if buf[i] == ' ' {
211 f[nf] = buf[p:i]
212 p = i + 1
213 nf++
214 }
215 }
216 f[nf] = buf[p:]
217 nf++
218
219 if nf != len(f) {
220 return NewError("invalid wait message")
221 }
222 w.Pid = int(atoi(f[0]))
223 w.Time[0] = uint32(atoi(f[1]))
224 w.Time[1] = uint32(atoi(f[2]))
225 w.Time[2] = uint32(atoi(f[3]))
Anthony Martin20943ba2011-06-20 13:34:10 +1000226 w.Msg = cstring(f[4])
Andrey Mirtchovskid1f48db2011-10-31 13:34:59 -0400227 if w.Msg == "''" {
228 // await() returns '' for no error
229 w.Msg = ""
230 }
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700231 return
232}
233
Lucio De Re087a3482011-11-16 17:37:54 -0500234func Unmount(name, old string) (err error) {
Brad Fitzpatrickbc9748e2015-02-27 19:34:56 -0800235 Fixwd()
Alexey Borzenkova1083692012-08-05 17:24:32 -0400236 oldp, err := BytePtrFromString(old)
237 if err != nil {
238 return err
239 }
240 oldptr := uintptr(unsafe.Pointer(oldp))
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700241
242 var r0 uintptr
Lucio De Re8ec32e82011-11-21 09:55:15 -0500243 var e ErrorString
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700244
245 // bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
246 if name == "" {
Alexey Borzenkova1083692012-08-05 17:24:32 -0400247 r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldptr, 0)
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700248 } else {
Alexey Borzenkova1083692012-08-05 17:24:32 -0400249 namep, err := BytePtrFromString(name)
250 if err != nil {
251 return err
252 }
253 r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0)
Russ Coxcf622d72014-09-08 16:59:59 -0400254 use(unsafe.Pointer(namep))
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700255 }
Russ Coxcf622d72014-09-08 16:59:59 -0400256 use(unsafe.Pointer(oldp))
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700257
Akshat Kumaraf582672012-10-01 10:09:08 +1000258 if int32(r0) == -1 {
Lucio De Re8ec32e82011-11-21 09:55:15 -0500259 err = e
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700260 }
261 return
262}
263
Lucio De Re087a3482011-11-16 17:37:54 -0500264func Fchdir(fd int) (err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700265 path, err := Fd2path(fd)
266
267 if err != nil {
268 return
269 }
270
271 return Chdir(path)
272}
273
Mikio Harae3e93b02012-01-19 14:52:28 +0900274type Timespec struct {
275 Sec int32
276 Nsec int32
277}
278
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700279type Timeval struct {
280 Sec int32
281 Usec int32
282}
283
284func NsecToTimeval(nsec int64) (tv Timeval) {
285 nsec += 999 // round up to microsecond
286 tv.Usec = int32(nsec % 1e9 / 1e3)
287 tv.Sec = int32(nsec / 1e9)
288 return
289}
290
Aram Hăvărneanu9c314112014-07-09 12:34:06 +0200291func nsec() int64 {
292 var scratch int64
293
294 r0, _, _ := Syscall(SYS_NSEC, uintptr(unsafe.Pointer(&scratch)), 0, 0)
295 // TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
296 if r0 == 0 {
297 return scratch
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700298 }
Aram Hăvărneanu9c314112014-07-09 12:34:06 +0200299 return int64(r0)
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700300}
301
Akshat Kumard2326fe2013-02-26 01:56:08 +0100302func Gettimeofday(tv *Timeval) error {
Aram Hăvărneanu9c314112014-07-09 12:34:06 +0200303 nsec := nsec()
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700304 *tv = NsecToTimeval(nsec)
Aram Hăvărneanu9c314112014-07-09 12:34:06 +0200305 return nil
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700306}
307
Aram Hăvărneanu9c314112014-07-09 12:34:06 +0200308func Getpagesize() int { return 0x1000 }
309
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700310func Getegid() (egid int) { return -1 }
311func Geteuid() (euid int) { return -1 }
312func Getgid() (gid int) { return -1 }
313func Getuid() (uid int) { return -1 }
314
Lucio De Re087a3482011-11-16 17:37:54 -0500315func Getgroups() (gids []int, err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700316 return make([]int, 0), nil
317}
318
Brad Fitzpatrickbc9748e2015-02-27 19:34:56 -0800319//sys open(path string, mode int) (fd int, err error)
320func Open(path string, mode int) (fd int, err error) {
321 Fixwd()
322 return open(path, mode)
323}
324
325//sys create(path string, mode int, perm uint32) (fd int, err error)
326func Create(path string, mode int, perm uint32) (fd int, err error) {
327 Fixwd()
328 return create(path, mode, perm)
329}
330
331//sys remove(path string) (err error)
332func Remove(path string) error {
333 Fixwd()
334 return remove(path)
335}
336
337//sys stat(path string, edir []byte) (n int, err error)
338func Stat(path string, edir []byte) (n int, err error) {
339 Fixwd()
340 return stat(path, edir)
341}
342
343//sys bind(name string, old string, flag int) (err error)
344func Bind(name string, old string, flag int) (err error) {
345 Fixwd()
346 return bind(name, old, flag)
347}
348
David du Colombierf0bd95b2015-03-01 17:30:47 +0100349//sys mount(fd int, afd int, old string, flag int, aname string) (err error)
350func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
351 Fixwd()
352 return mount(fd, afd, old, flag, aname)
353}
354
Brad Fitzpatrickbc9748e2015-02-27 19:34:56 -0800355//sys wstat(path string, edir []byte) (err error)
356func Wstat(path string, edir []byte) (err error) {
357 Fixwd()
358 return wstat(path, edir)
359}
360
361//sys chdir(path string) (err error)
Lucio De Re8ec32e82011-11-21 09:55:15 -0500362//sys Dup(oldfd int, newfd int) (fd int, err error)
Lucio De Re8ec32e82011-11-21 09:55:15 -0500363//sys Pread(fd int, p []byte, offset int64) (n int, err error)
364//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
365//sys Close(fd int) (err error)
Lucio De Re8ec32e82011-11-21 09:55:15 -0500366//sys Fstat(fd int, edir []byte) (n int, err error)
Lucio De Re8ec32e82011-11-21 09:55:15 -0500367//sys Fwstat(fd int, edir []byte) (err error)