github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/go/src/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 if err == nil { 202 p[0] = int(pp[0]) 203 p[1] = int(pp[1]) 204 } 205 return 206 } 207 208 // Underlying system call writes to newoffset via pointer. 209 // Implemented in assembly to avoid allocation. 210 func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string) 211 212 func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { 213 newoffset, e := seek(0, fd, offset, whence) 214 215 if newoffset == -1 { 216 err = NewError(e) 217 } 218 return 219 } 220 221 func Mkdir(path string, mode uint32) (err error) { 222 // If path exists and is not a directory, Create will fail silently. 223 // Work around this by rejecting Mkdir if path exists. 224 statbuf := make([]byte, bitSize16) 225 // Remove any trailing slashes from path, otherwise the Stat will 226 // fail with ENOTDIR. 227 n := len(path) 228 for n > 1 && path[n-1] == '/' { 229 n-- 230 } 231 _, err = Stat(path[0:n], statbuf) 232 if err == nil { 233 return EEXIST 234 } 235 236 fd, err := Create(path, O_RDONLY, DMDIR|mode) 237 238 if fd != -1 { 239 Close(fd) 240 } 241 242 return 243 } 244 245 type Waitmsg struct { 246 Pid int 247 Time [3]uint32 248 Msg string 249 } 250 251 func (w Waitmsg) Exited() bool { return true } 252 func (w Waitmsg) Signaled() bool { return false } 253 254 func (w Waitmsg) ExitStatus() int { 255 if len(w.Msg) == 0 { 256 // a normal exit returns no message 257 return 0 258 } 259 return 1 260 } 261 262 //sys await(s []byte) (n int, err error) 263 func Await(w *Waitmsg) (err error) { 264 var buf [512]byte 265 var f [5][]byte 266 267 n, err := await(buf[:]) 268 269 if err != nil || w == nil { 270 return 271 } 272 273 nf := 0 274 p := 0 275 for i := 0; i < n && nf < len(f)-1; i++ { 276 if buf[i] == ' ' { 277 f[nf] = buf[p:i] 278 p = i + 1 279 nf++ 280 } 281 } 282 f[nf] = buf[p:] 283 nf++ 284 285 if nf != len(f) { 286 return NewError("invalid wait message") 287 } 288 w.Pid = int(atoi(f[0])) 289 w.Time[0] = uint32(atoi(f[1])) 290 w.Time[1] = uint32(atoi(f[2])) 291 w.Time[2] = uint32(atoi(f[3])) 292 w.Msg = cstring(f[4]) 293 if w.Msg == "''" { 294 // await() returns '' for no error 295 w.Msg = "" 296 } 297 return 298 } 299 300 func Unmount(name, old string) (err error) { 301 fixwd(name, old) 302 oldp, err := BytePtrFromString(old) 303 if err != nil { 304 return err 305 } 306 oldptr := uintptr(unsafe.Pointer(oldp)) 307 308 var r0 uintptr 309 var e ErrorString 310 311 // bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted. 312 if name == "" { 313 r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldptr, 0) 314 } else { 315 namep, err := BytePtrFromString(name) 316 if err != nil { 317 return err 318 } 319 r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0) 320 } 321 322 if int32(r0) == -1 { 323 err = e 324 } 325 return 326 } 327 328 func Fchdir(fd int) (err error) { 329 path, err := Fd2path(fd) 330 331 if err != nil { 332 return 333 } 334 335 return Chdir(path) 336 } 337 338 type Timespec struct { 339 Sec int32 340 Nsec int32 341 } 342 343 type Timeval struct { 344 Sec int32 345 Usec int32 346 } 347 348 func NsecToTimeval(nsec int64) (tv Timeval) { 349 nsec += 999 // round up to microsecond 350 tv.Usec = int32(nsec % 1e9 / 1e3) 351 tv.Sec = int32(nsec / 1e9) 352 return 353 } 354 355 func nsec() int64 { 356 var scratch int64 357 358 r0, _, _ := Syscall(SYS_NSEC, uintptr(unsafe.Pointer(&scratch)), 0, 0) 359 // TODO(aram): remove hack after I fix _nsec in the pc64 kernel. 360 if r0 == 0 { 361 return scratch 362 } 363 return int64(r0) 364 } 365 366 func Gettimeofday(tv *Timeval) error { 367 nsec := nsec() 368 *tv = NsecToTimeval(nsec) 369 return nil 370 } 371 372 func Getegid() (egid int) { return -1 } 373 func Geteuid() (euid int) { return -1 } 374 func Getgid() (gid int) { return -1 } 375 func Getuid() (uid int) { return -1 } 376 377 func Getgroups() (gids []int, err error) { 378 return make([]int, 0), nil 379 } 380 381 //sys open(path string, mode int) (fd int, err error) 382 func Open(path string, mode int) (fd int, err error) { 383 fixwd(path) 384 return open(path, mode) 385 } 386 387 //sys create(path string, mode int, perm uint32) (fd int, err error) 388 func Create(path string, mode int, perm uint32) (fd int, err error) { 389 fixwd(path) 390 return create(path, mode, perm) 391 } 392 393 //sys remove(path string) (err error) 394 func Remove(path string) error { 395 fixwd(path) 396 return remove(path) 397 } 398 399 //sys stat(path string, edir []byte) (n int, err error) 400 func Stat(path string, edir []byte) (n int, err error) { 401 fixwd(path) 402 return stat(path, edir) 403 } 404 405 //sys bind(name string, old string, flag int) (err error) 406 func Bind(name string, old string, flag int) (err error) { 407 fixwd(name, old) 408 return bind(name, old, flag) 409 } 410 411 //sys mount(fd int, afd int, old string, flag int, aname string) (err error) 412 func Mount(fd int, afd int, old string, flag int, aname string) (err error) { 413 fixwd(old) 414 return mount(fd, afd, old, flag, aname) 415 } 416 417 //sys wstat(path string, edir []byte) (err error) 418 func Wstat(path string, edir []byte) (err error) { 419 fixwd(path) 420 return wstat(path, edir) 421 } 422 423 //sys chdir(path string) (err error) 424 //sys Dup(oldfd int, newfd int) (fd int, err error) 425 //sys Pread(fd int, p []byte, offset int64) (n int, err error) 426 //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) 427 //sys Close(fd int) (err error) 428 //sys Fstat(fd int, edir []byte) (n int, err error) 429 //sys Fwstat(fd int, edir []byte) (err error)