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