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