blob: c1f45f3a2c0477c1d0dd6f22e578add3387ed6bc [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
26var (
27 Stdin = 0
28 Stdout = 1
29 Stderr = 2
30
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040031 EAFNOSUPPORT = NewError("address family not supported by protocol")
32 EISDIR = NewError("file is a directory")
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070033)
34
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040035// For testing: clients can set this flag to force
36// creation of IPv6 sockets to return EAFNOSUPPORT.
37var SocketDisableIPv6 bool
38
Lucio De Re8ec32e82011-11-21 09:55:15 -050039func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err ErrorString)
40func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err ErrorString)
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070041func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
42func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
43
44func atoi(b []byte) (n uint) {
45 n = 0
46 for i := 0; i < len(b); i++ {
47 n = n*10 + uint(b[i]-'0')
48 }
49 return
50}
51
52func cstring(s []byte) string {
Robert Griesemera2e28682011-04-13 15:13:59 -070053 for i := range s {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070054 if s[i] == 0 {
55 return string(s[0:i])
56 }
57 }
58 return string(s)
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
70func Getpagesize() int { return 4096 }
71
Akshat Kumar49a7da22012-04-19 16:31:26 -070072// Implemented in assembly to import from runtime.
73func exit(int)
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070074
Akshat Kumar49a7da22012-04-19 16:31:26 -070075func Exit(code int) { exit(code) }
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070076
Lucio De Re087a3482011-11-16 17:37:54 -050077func readnum(path string) (uint, error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -070078 var b [12]byte
79
80 fd, e := Open(path, O_RDONLY)
81 if e != nil {
82 return 0, e
83 }
84 defer Close(fd)
85
86 n, e := Pread(fd, b[:], 0)
87
88 if e != nil {
89 return 0, e
90 }
91
92 m := 0
93 for ; m < n && b[m] == ' '; m++ {
94 }
95
96 return atoi(b[m : n-1]), nil
97}
98
99func Getpid() (pid int) {
100 n, _ := readnum("#c/pid")
101 return int(n)
102}
103
104func Getppid() (ppid int) {
105 n, _ := readnum("#c/ppid")
106 return int(n)
107}
108
Lucio De Re087a3482011-11-16 17:37:54 -0500109func Read(fd int, p []byte) (n int, err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700110 return Pread(fd, p, -1)
111}
112
Lucio De Re087a3482011-11-16 17:37:54 -0500113func Write(fd int, p []byte) (n int, err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700114 return Pwrite(fd, p, -1)
115}
116
Lucio De Re087a3482011-11-16 17:37:54 -0500117func Getwd() (wd string, err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700118 fd, e := Open(".", O_RDONLY)
119
120 if e != nil {
121 return "", e
122 }
123 defer Close(fd)
124
125 return Fd2path(fd)
126}
127
Lucio De Re087a3482011-11-16 17:37:54 -0500128//sys fd2path(fd int, buf []byte) (err error)
129func Fd2path(fd int) (path string, err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700130 var buf [512]byte
131
132 e := fd2path(fd, buf[:])
133 if e != nil {
134 return "", e
135 }
136 return cstring(buf[:]), nil
137}
138
Lucio De Re087a3482011-11-16 17:37:54 -0500139//sys pipe(p *[2]_C_int) (err error)
140func Pipe(p []int) (err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700141 if len(p) != 2 {
142 return NewError("bad arg in system call")
143 }
144 var pp [2]_C_int
145 err = pipe(&pp)
146 p[0] = int(pp[0])
147 p[1] = int(pp[1])
148 return
149}
150
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700151// Underlying system call writes to newoffset via pointer.
152// Implemented in assembly to avoid allocation.
153func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
154
Lucio De Re087a3482011-11-16 17:37:54 -0500155func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700156 newoffset, e := seek(0, fd, offset, whence)
157
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700158 if newoffset == -1 {
159 err = NewError(e)
160 }
161 return
162}
163
Lucio De Re087a3482011-11-16 17:37:54 -0500164func Mkdir(path string, mode uint32) (err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700165 fd, err := Create(path, O_RDONLY, DMDIR|mode)
166
167 if fd != -1 {
168 Close(fd)
169 }
170
171 return
172}
173
174type Waitmsg struct {
175 Pid int
176 Time [3]uint32
177 Msg string
178}
179
Anthony Martin20943ba2011-06-20 13:34:10 +1000180func (w Waitmsg) Exited() bool { return true }
181func (w Waitmsg) Signaled() bool { return false }
182
183func (w Waitmsg) ExitStatus() int {
184 if len(w.Msg) == 0 {
185 // a normal exit returns no message
186 return 0
187 }
188 return 1
189}
190
Lucio De Re087a3482011-11-16 17:37:54 -0500191//sys await(s []byte) (n int, err error)
192func Await(w *Waitmsg) (err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700193 var buf [512]byte
194 var f [5][]byte
195
196 n, err := await(buf[:])
197
198 if err != nil || w == nil {
199 return
200 }
201
202 nf := 0
203 p := 0
204 for i := 0; i < n && nf < len(f)-1; i++ {
205 if buf[i] == ' ' {
206 f[nf] = buf[p:i]
207 p = i + 1
208 nf++
209 }
210 }
211 f[nf] = buf[p:]
212 nf++
213
214 if nf != len(f) {
215 return NewError("invalid wait message")
216 }
217 w.Pid = int(atoi(f[0]))
218 w.Time[0] = uint32(atoi(f[1]))
219 w.Time[1] = uint32(atoi(f[2]))
220 w.Time[2] = uint32(atoi(f[3]))
Anthony Martin20943ba2011-06-20 13:34:10 +1000221 w.Msg = cstring(f[4])
Andrey Mirtchovskid1f48db2011-10-31 13:34:59 -0400222 if w.Msg == "''" {
223 // await() returns '' for no error
224 w.Msg = ""
225 }
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700226 return
227}
228
Lucio De Re087a3482011-11-16 17:37:54 -0500229func Unmount(name, old string) (err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700230 oldp := uintptr(unsafe.Pointer(StringBytePtr(old)))
231
232 var r0 uintptr
Lucio De Re8ec32e82011-11-21 09:55:15 -0500233 var e ErrorString
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700234
235 // bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
236 if name == "" {
237 r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldp, 0)
238 } else {
239 r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(name))), oldp, 0)
240 }
241
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700242 if int(r0) == -1 {
Lucio De Re8ec32e82011-11-21 09:55:15 -0500243 err = e
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700244 }
245 return
246}
247
Lucio De Re087a3482011-11-16 17:37:54 -0500248func Fchdir(fd int) (err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700249 path, err := Fd2path(fd)
250
251 if err != nil {
252 return
253 }
254
255 return Chdir(path)
256}
257
Mikio Harae3e93b02012-01-19 14:52:28 +0900258type Timespec struct {
259 Sec int32
260 Nsec int32
261}
262
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700263type Timeval struct {
264 Sec int32
265 Usec int32
266}
267
268func NsecToTimeval(nsec int64) (tv Timeval) {
269 nsec += 999 // round up to microsecond
270 tv.Usec = int32(nsec % 1e9 / 1e3)
271 tv.Sec = int32(nsec / 1e9)
272 return
273}
274
Lucio De Re087a3482011-11-16 17:37:54 -0500275func DecodeBintime(b []byte) (nsec int64, err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700276 if len(b) != 8 {
277 return -1, NewError("bad /dev/bintime format")
278 }
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700279 nsec = int64(b[0])<<56 |
280 int64(b[1])<<48 |
281 int64(b[2])<<40 |
282 int64(b[3])<<32 |
283 int64(b[4])<<24 |
284 int64(b[5])<<16 |
285 int64(b[6])<<8 |
286 int64(b[7])
287 return
288}
289
Lucio De Re087a3482011-11-16 17:37:54 -0500290func Gettimeofday(tv *Timeval) (err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700291 // TODO(paulzhol):
292 // avoid reopening a file descriptor for /dev/bintime on each call,
293 // use lower-level calls to avoid allocation.
294
295 var b [8]byte
296 var nsec int64
297
298 fd, e := Open("/dev/bintime", O_RDONLY)
299 if e != nil {
300 return e
301 }
302 defer Close(fd)
303
304 if _, e = Pread(fd, b[:], 0); e != nil {
305 return e
306 }
307
308 if nsec, e = DecodeBintime(b[:]); e != nil {
309 return e
310 }
311 *tv = NsecToTimeval(nsec)
312
313 return e
314}
315
316func Getegid() (egid int) { return -1 }
317func Geteuid() (euid int) { return -1 }
318func Getgid() (gid int) { return -1 }
319func Getuid() (uid int) { return -1 }
320
Lucio De Re087a3482011-11-16 17:37:54 -0500321func Getgroups() (gids []int, err error) {
Yuval Pavel Zholkover1cc4a5c2011-04-02 14:24:03 -0700322 return make([]int, 0), nil
323}
324
Mikio Hara03d4c7c2012-02-17 10:59:30 +0900325type Signal int
326
327func (s Signal) Signal() {}
328
329func (s Signal) String() string {
330 return ""
331}
332
Lucio De Re8ec32e82011-11-21 09:55:15 -0500333//sys Dup(oldfd int, newfd int) (fd int, err error)
334//sys Open(path string, mode int) (fd int, err error)
335//sys Create(path string, mode int, perm uint32) (fd int, err error)
336//sys Remove(path string) (err error)
337//sys Pread(fd int, p []byte, offset int64) (n int, err error)
338//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
339//sys Close(fd int) (err error)
340//sys Chdir(path string) (err error)
341//sys Bind(name string, old string, flag int) (err error)
342//sys Mount(fd int, afd int, old string, flag int, aname string) (err error)
343//sys Stat(path string, edir []byte) (n int, err error)
344//sys Fstat(fd int, edir []byte) (n int, err error)
345//sys Wstat(path string, edir []byte) (err error)
346//sys Fwstat(fd int, edir []byte) (err error)