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