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