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