1// Copyright 2018 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// Aix 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 12package syscall 13 14import ( 15 "unsafe" 16) 17 18func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) 19func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 20func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) 21func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 22 23// Implemented in runtime/syscall_aix.go. 24func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 25func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 26 27// Constant expected by package but not supported 28const ( 29 _ = iota 30 TIOCSCTTY 31 SYS_EXECVE 32 SYS_FCNTL 33) 34 35const ( 36 F_DUPFD_CLOEXEC = 0 37 // AF_LOCAL doesn't exist on AIX 38 AF_LOCAL = AF_UNIX 39 40 _F_DUP2FD_CLOEXEC = 0 41) 42 43func (ts *StTimespec_t) Unix() (sec int64, nsec int64) { 44 return int64(ts.Sec), int64(ts.Nsec) 45} 46 47func (ts *StTimespec_t) Nano() int64 { 48 return int64(ts.Sec)*1e9 + int64(ts.Nsec) 49} 50 51/* 52 * Wrapped 53 */ 54 55func Access(path string, mode uint32) (err error) { 56 return Faccessat(_AT_FDCWD, path, mode, 0) 57} 58 59// fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX 60// There is no way to create a custom fcntl and to keep //sys fcntl easily, 61// because we need fcntl name for its libc symbol. This is linked with the script. 62// But, as fcntl is currently not exported and isn't called with F_DUP2FD, 63// it doesn't matter. 64//sys fcntl(fd int, cmd int, arg int) (val int, err error) 65//sys Dup2(old int, new int) (err error) 66 67//sysnb pipe(p *[2]_C_int) (err error) 68 69func Pipe(p []int) (err error) { 70 if len(p) != 2 { 71 return EINVAL 72 } 73 var pp [2]_C_int 74 err = pipe(&pp) 75 if err == nil { 76 p[0] = int(pp[0]) 77 p[1] = int(pp[1]) 78 } 79 return 80} 81 82//sys readlink(path string, buf []byte, bufSize uint64) (n int, err error) 83 84func Readlink(path string, buf []byte) (n int, err error) { 85 s := uint64(len(buf)) 86 return readlink(path, buf, s) 87} 88 89//sys utimes(path string, times *[2]Timeval) (err error) 90 91func Utimes(path string, tv []Timeval) error { 92 if len(tv) != 2 { 93 return EINVAL 94 } 95 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 96} 97 98//sys utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error) 99 100func UtimesNano(path string, ts []Timespec) error { 101 if len(ts) != 2 { 102 return EINVAL 103 } 104 return utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) 105} 106 107//sys unlinkat(dirfd int, path string, flags int) (err error) 108 109func Unlinkat(dirfd int, path string) (err error) { 110 return unlinkat(dirfd, path, 0) 111} 112 113//sys getcwd(buf *byte, size uint64) (err error) 114 115const ImplementsGetwd = true 116 117func Getwd() (ret string, err error) { 118 for len := uint64(4096); ; len *= 2 { 119 b := make([]byte, len) 120 err := getcwd(&b[0], len) 121 if err == nil { 122 i := 0 123 for b[i] != 0 { 124 i++ 125 } 126 return string(b[0:i]), nil 127 } 128 if err != ERANGE { 129 return "", err 130 } 131 } 132} 133 134func Getcwd(buf []byte) (n int, err error) { 135 err = getcwd(&buf[0], uint64(len(buf))) 136 if err == nil { 137 i := 0 138 for buf[i] != 0 { 139 i++ 140 } 141 n = i + 1 142 } 143 return 144} 145 146//sysnb getgroups(ngid int, gid *_Gid_t) (n int, err error) 147//sysnb setgroups(ngid int, gid *_Gid_t) (err error) 148 149func Getgroups() (gids []int, err error) { 150 n, err := getgroups(0, nil) 151 if err != nil { 152 return nil, err 153 } 154 if n == 0 { 155 return nil, nil 156 } 157 158 // Sanity check group count. Max is 16 on BSD. 159 if n < 0 || n > 1000 { 160 return nil, EINVAL 161 } 162 163 a := make([]_Gid_t, n) 164 n, err = getgroups(n, &a[0]) 165 if err != nil { 166 return nil, err 167 } 168 gids = make([]int, n) 169 for i, v := range a[0:n] { 170 gids[i] = int(v) 171 } 172 return 173} 174 175func Setgroups(gids []int) (err error) { 176 if len(gids) == 0 { 177 return setgroups(0, nil) 178 } 179 180 a := make([]_Gid_t, len(gids)) 181 for i, v := range gids { 182 a[i] = _Gid_t(v) 183 } 184 return setgroups(len(a), &a[0]) 185} 186 187func direntIno(buf []byte) (uint64, bool) { 188 return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino)) 189} 190 191func direntReclen(buf []byte) (uint64, bool) { 192 return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) 193} 194 195func direntNamlen(buf []byte) (uint64, bool) { 196 reclen, ok := direntReclen(buf) 197 if !ok { 198 return 0, false 199 } 200 return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true 201} 202 203func Gettimeofday(tv *Timeval) (err error) { 204 err = gettimeofday(tv, nil) 205 return 206} 207 208// TODO 209func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { 210 return -1, ENOSYS 211} 212 213//sys getdirent(fd int, buf []byte) (n int, err error) 214 215func ReadDirent(fd int, buf []byte) (n int, err error) { 216 return getdirent(fd, buf) 217} 218 219//sys wait4(pid _Pid_t, status *_C_int, options int, rusage *Rusage) (wpid _Pid_t, err error) 220 221func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { 222 var status _C_int 223 var r _Pid_t 224 err = ERESTART 225 // AIX wait4 may return with ERESTART errno, while the process is still 226 // active. 227 for err == ERESTART { 228 r, err = wait4(_Pid_t(pid), &status, options, rusage) 229 } 230 wpid = int(r) 231 if wstatus != nil { 232 *wstatus = WaitStatus(status) 233 } 234 return 235} 236 237//sys fsyncRange(fd int, how int, start int64, length int64) (err error) = fsync_range 238 239func Fsync(fd int) error { 240 return fsyncRange(fd, O_SYNC, 0, 0) 241} 242 243/* 244 * Socket 245 */ 246//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) 247//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) 248//sys Getkerninfo(op int32, where uintptr, size uintptr, arg int64) (i int32, err error) 249//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) 250//sys Listen(s int, backlog int) (err error) 251//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) 252//sys socket(domain int, typ int, proto int) (fd int, err error) 253//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) 254//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) 255//sys getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) 256//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) 257//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) 258//sys Shutdown(s int, how int) (err error) 259 260// In order to use msghdr structure with Control, Controllen in golang.org/x/net, 261// nrecvmsg and nsendmsg must be used. 262//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = nrecvmsg 263//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = nsendmsg 264 265func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { 266 if sa.Port < 0 || sa.Port > 0xFFFF { 267 return nil, 0, EINVAL 268 } 269 sa.raw.Family = AF_INET 270 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 271 p[0] = byte(sa.Port >> 8) 272 p[1] = byte(sa.Port) 273 sa.raw.Addr = sa.Addr 274 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil 275} 276 277func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { 278 if sa.Port < 0 || sa.Port > 0xFFFF { 279 return nil, 0, EINVAL 280 } 281 sa.raw.Family = AF_INET6 282 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 283 p[0] = byte(sa.Port >> 8) 284 p[1] = byte(sa.Port) 285 sa.raw.Scope_id = sa.ZoneId 286 sa.raw.Addr = sa.Addr 287 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil 288} 289 290func (sa *RawSockaddrUnix) setLen(n int) { 291 sa.Len = uint8(3 + n) // 2 for Family, Len; 1 for NUL. 292} 293 294func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { 295 name := sa.Name 296 n := len(name) 297 if n > len(sa.raw.Path) { 298 return nil, 0, EINVAL 299 } 300 sa.raw.Family = AF_UNIX 301 sa.raw.setLen(n) 302 for i := 0; i < n; i++ { 303 sa.raw.Path[i] = uint8(name[i]) 304 } 305 // length is family (uint16), name, NUL. 306 sl := _Socklen(2) 307 if n > 0 { 308 sl += _Socklen(n) + 1 309 } 310 311 return unsafe.Pointer(&sa.raw), sl, nil 312} 313 314func Getsockname(fd int) (sa Sockaddr, err error) { 315 var rsa RawSockaddrAny 316 var len _Socklen = SizeofSockaddrAny 317 if err = getsockname(fd, &rsa, &len); err != nil { 318 return 319 } 320 return anyToSockaddr(&rsa) 321} 322 323//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) 324 325func Accept(fd int) (nfd int, sa Sockaddr, err error) { 326 var rsa RawSockaddrAny 327 var len _Socklen = SizeofSockaddrAny 328 nfd, err = accept(fd, &rsa, &len) 329 if err != nil { 330 return 331 } 332 sa, err = anyToSockaddr(&rsa) 333 if err != nil { 334 Close(nfd) 335 nfd = 0 336 } 337 return 338} 339 340func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { 341 var msg Msghdr 342 msg.Name = (*byte)(unsafe.Pointer(rsa)) 343 msg.Namelen = uint32(SizeofSockaddrAny) 344 var iov Iovec 345 if len(p) > 0 { 346 iov.Base = &p[0] 347 iov.SetLen(len(p)) 348 } 349 var dummy byte 350 if len(oob) > 0 { 351 var sockType int 352 sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE) 353 if err != nil { 354 return 355 } 356 // receive at least one normal byte 357 if sockType != SOCK_DGRAM && len(p) == 0 { 358 iov.Base = &dummy 359 iov.SetLen(1) 360 } 361 msg.Control = &oob[0] 362 msg.SetControllen(len(oob)) 363 } 364 msg.Iov = &iov 365 msg.Iovlen = 1 366 if n, err = recvmsg(fd, &msg, flags); err != nil { 367 return 368 } 369 oobn = int(msg.Controllen) 370 recvflags = int(msg.Flags) 371 return 372} 373 374func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { 375 var msg Msghdr 376 msg.Name = (*byte)(ptr) 377 msg.Namelen = uint32(salen) 378 var iov Iovec 379 if len(p) > 0 { 380 iov.Base = &p[0] 381 iov.SetLen(len(p)) 382 } 383 var dummy byte 384 if len(oob) > 0 { 385 var sockType int 386 sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE) 387 if err != nil { 388 return 0, err 389 } 390 // send at least one normal byte 391 if sockType != SOCK_DGRAM && len(p) == 0 { 392 iov.Base = &dummy 393 iov.SetLen(1) 394 } 395 msg.Control = &oob[0] 396 msg.SetControllen(len(oob)) 397 } 398 msg.Iov = &iov 399 msg.Iovlen = 1 400 if n, err = sendmsg(fd, &msg, flags); err != nil { 401 return 0, err 402 } 403 if len(oob) > 0 && len(p) == 0 { 404 n = 0 405 } 406 return n, nil 407} 408 409func (sa *RawSockaddrUnix) getLen() (int, error) { 410 // Some versions of AIX have a bug in getsockname (see IV78655). 411 // We can't rely on sa.Len being set correctly. 412 n := SizeofSockaddrUnix - 3 // subtract leading Family, Len, terminating NUL. 413 for i := 0; i < n; i++ { 414 if sa.Path[i] == 0 { 415 n = i 416 break 417 } 418 } 419 return n, nil 420} 421 422func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { 423 switch rsa.Addr.Family { 424 case AF_UNIX: 425 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) 426 sa := new(SockaddrUnix) 427 n, err := pp.getLen() 428 if err != nil { 429 return nil, err 430 } 431 sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n)) 432 return sa, nil 433 434 case AF_INET: 435 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) 436 sa := new(SockaddrInet4) 437 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 438 sa.Port = int(p[0])<<8 + int(p[1]) 439 sa.Addr = pp.Addr 440 return sa, nil 441 442 case AF_INET6: 443 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) 444 sa := new(SockaddrInet6) 445 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 446 sa.Port = int(p[0])<<8 + int(p[1]) 447 sa.Addr = pp.Addr 448 return sa, nil 449 } 450 return nil, EAFNOSUPPORT 451} 452 453type SockaddrDatalink struct { 454 Len uint8 455 Family uint8 456 Index uint16 457 Type uint8 458 Nlen uint8 459 Alen uint8 460 Slen uint8 461 Data [120]uint8 462 raw RawSockaddrDatalink 463} 464 465/* 466 * Wait 467 */ 468 469type WaitStatus uint32 470 471func (w WaitStatus) Stopped() bool { return w&0x40 != 0 } 472func (w WaitStatus) StopSignal() Signal { 473 if !w.Stopped() { 474 return -1 475 } 476 return Signal(w>>8) & 0xFF 477} 478 479func (w WaitStatus) Exited() bool { return w&0xFF == 0 } 480func (w WaitStatus) ExitStatus() int { 481 if !w.Exited() { 482 return -1 483 } 484 return int((w >> 8) & 0xFF) 485} 486 487func (w WaitStatus) Signaled() bool { return w&0x40 == 0 && w&0xFF != 0 } 488func (w WaitStatus) Signal() Signal { 489 if !w.Signaled() { 490 return -1 491 } 492 return Signal(w>>16) & 0xFF 493} 494 495func (w WaitStatus) Continued() bool { return w&0x01000000 != 0 } 496 497func (w WaitStatus) CoreDump() bool { return w&0x80 == 0x80 } 498 499func (w WaitStatus) TrapCause() int { return -1 } 500 501/* 502 * ptrace 503 */ 504 505//sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) 506//sys ptrace64(request int, id int64, addr int64, data int, buff uintptr) (err error) 507//sys ptrace64Ptr(request int, id int64, addr int64, data int, buff unsafe.Pointer) (err error) = ptrace64 508 509func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno { 510 if request == PTRACE_TRACEME { 511 // Convert to AIX ptrace call. 512 err := ptrace64(PT_TRACE_ME, 0, 0, 0, 0) 513 if err != nil { 514 return err.(Errno) 515 } 516 return 0 517 } 518 return ENOSYS 519} 520 521func ptracePeek(pid int, addr uintptr, out []byte) (count int, err error) { 522 n := 0 523 for len(out) > 0 { 524 bsize := len(out) 525 if bsize > 1024 { 526 bsize = 1024 527 } 528 err = ptrace64Ptr(PT_READ_BLOCK, int64(pid), int64(addr), bsize, unsafe.Pointer(&out[0])) 529 if err != nil { 530 return 0, err 531 } 532 addr += uintptr(bsize) 533 n += bsize 534 out = out[n:] 535 } 536 return n, nil 537} 538 539func PtracePeekText(pid int, addr uintptr, out []byte) (count int, err error) { 540 return ptracePeek(pid, addr, out) 541} 542 543func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) { 544 return ptracePeek(pid, addr, out) 545} 546 547func ptracePoke(pid int, addr uintptr, data []byte) (count int, err error) { 548 n := 0 549 for len(data) > 0 { 550 bsize := len(data) 551 if bsize > 1024 { 552 bsize = 1024 553 } 554 err = ptrace64Ptr(PT_WRITE_BLOCK, int64(pid), int64(addr), bsize, unsafe.Pointer(&data[0])) 555 if err != nil { 556 return 0, err 557 } 558 addr += uintptr(bsize) 559 n += bsize 560 data = data[n:] 561 } 562 return n, nil 563} 564 565func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) { 566 return ptracePoke(pid, addr, data) 567} 568 569func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) { 570 return ptracePoke(pid, addr, data) 571} 572 573func PtraceCont(pid int, signal int) (err error) { 574 return ptrace64(PT_CONTINUE, int64(pid), 1, signal, 0) 575} 576 577func PtraceSingleStep(pid int) (err error) { return ptrace64(PT_STEP, int64(pid), 1, 0, 0) } 578 579func PtraceAttach(pid int) (err error) { return ptrace64(PT_ATTACH, int64(pid), 0, 0, 0) } 580 581func PtraceDetach(pid int) (err error) { return ptrace64(PT_DETACH, int64(pid), 0, 0, 0) } 582 583/* 584 * Direct access 585 */ 586 587//sys Acct(path string) (err error) 588//sys Chdir(path string) (err error) 589//sys Chmod(path string, mode uint32) (err error) 590//sys Chown(path string, uid int, gid int) (err error) 591//sys Chroot(path string) (err error) 592//sys Close(fd int) (err error) 593//sys Dup(fd int) (nfd int, err error) 594//sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error) 595//sys Fchdir(fd int) (err error) 596//sys Fchmod(fd int, mode uint32) (err error) 597//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) 598//sys Fchown(fd int, uid int, gid int) (err error) 599//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) 600//sys Fpathconf(fd int, name int) (val int, err error) 601//sys Fstat(fd int, stat *Stat_t) (err error) 602//sys Fstatfs(fd int, buf *Statfs_t) (err error) 603//sys Ftruncate(fd int, length int64) (err error) 604//sysnb Getgid() (gid int) 605//sysnb Getpid() (pid int) 606//sys Geteuid() (euid int) 607//sys Getegid() (egid int) 608//sys Getppid() (ppid int) 609//sys Getpriority(which int, who int) (n int, err error) 610//sysnb Getrlimit(which int, lim *Rlimit) (err error) 611//sysnb Getrusage(who int, rusage *Rusage) (err error) 612//sysnb Getuid() (uid int) 613//sys Kill(pid int, signum Signal) (err error) 614//sys Lchown(path string, uid int, gid int) (err error) 615//sys Link(path string, link string) (err error) 616//sys Lstat(path string, stat *Stat_t) (err error) 617//sys Mkdir(path string, mode uint32) (err error) 618//sys Mkdirat(dirfd int, path string, mode uint32) (err error) 619//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) 620//sys Open(path string, mode int, perm uint32) (fd int, err error) 621//sys pread(fd int, p []byte, offset int64) (n int, err error) 622//sys pwrite(fd int, p []byte, offset int64) (n int, err error) 623//sys read(fd int, p []byte) (n int, err error) 624//sys Reboot(how int) (err error) 625//sys Rename(from string, to string) (err error) 626//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) 627//sys Rmdir(path string) (err error) 628//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek 629//sysnb Setegid(egid int) (err error) 630//sysnb Seteuid(euid int) (err error) 631//sysnb Setgid(gid int) (err error) 632//sysnb Setuid(uid int) (err error) 633//sysnb Setpgid(pid int, pgid int) (err error) 634//sys Setpriority(which int, who int, prio int) (err error) 635//sysnb Setregid(rgid int, egid int) (err error) 636//sysnb Setreuid(ruid int, euid int) (err error) 637//sysnb setrlimit(which int, lim *Rlimit) (err error) 638//sys Stat(path string, stat *Stat_t) (err error) 639//sys Statfs(path string, buf *Statfs_t) (err error) 640//sys Symlink(path string, link string) (err error) 641//sys Truncate(path string, length int64) (err error) 642//sys Umask(newmask int) (oldmask int) 643//sys Unlink(path string) (err error) 644//sysnb Uname(buf *Utsname) (err error) 645//sys write(fd int, p []byte) (n int, err error) 646//sys writev(fd int, iovecs []Iovec) (n uintptr, err error) 647 648//sys gettimeofday(tv *Timeval, tzp *Timezone) (err error) 649 650func setTimespec(sec, nsec int64) Timespec { 651 return Timespec{Sec: sec, Nsec: nsec} 652} 653 654func setTimeval(sec, usec int64) Timeval { 655 return Timeval{Sec: sec, Usec: int32(usec)} 656} 657 658func readlen(fd int, buf *byte, nbuf int) (n int, err error) { 659 r0, _, e1 := syscall6(uintptr(unsafe.Pointer(&libc_read)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0) 660 n = int(r0) 661 if e1 != 0 { 662 err = e1 663 } 664 return 665} 666 667/* 668 * Map 669 */ 670 671var mapper = &mmapper{ 672 active: make(map[*byte][]byte), 673 mmap: mmap, 674 munmap: munmap, 675} 676 677//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) 678//sys munmap(addr uintptr, length uintptr) (err error) 679 680func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { 681 return mapper.Mmap(fd, offset, length, prot, flags) 682} 683 684func Munmap(b []byte) (err error) { 685 return mapper.Munmap(b) 686} 687