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//go:build aix 6// +build aix 7 8// Aix system calls. 9// This file is compiled as ordinary Go code, 10// but it is also input to mksyscall, 11// which parses the //sys lines and generates system call stubs. 12// Note that sometimes we use a lowercase //sys name and 13// wrap it in our own nicer implementation. 14 15package unix 16 17import "unsafe" 18 19/* 20 * Wrapped 21 */ 22 23func Access(path string, mode uint32) (err error) { 24 return Faccessat(AT_FDCWD, path, mode, 0) 25} 26 27func Chmod(path string, mode uint32) (err error) { 28 return Fchmodat(AT_FDCWD, path, mode, 0) 29} 30 31func Chown(path string, uid int, gid int) (err error) { 32 return Fchownat(AT_FDCWD, path, uid, gid, 0) 33} 34 35func Creat(path string, mode uint32) (fd int, err error) { 36 return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode) 37} 38 39//sys utimes(path string, times *[2]Timeval) (err error) 40func Utimes(path string, tv []Timeval) error { 41 if len(tv) != 2 { 42 return EINVAL 43 } 44 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 45} 46 47//sys utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error) 48func UtimesNano(path string, ts []Timespec) error { 49 if len(ts) != 2 { 50 return EINVAL 51 } 52 return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) 53} 54 55func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error { 56 if ts == nil { 57 return utimensat(dirfd, path, nil, flags) 58 } 59 if len(ts) != 2 { 60 return EINVAL 61 } 62 return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags) 63} 64 65func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { 66 if sa.Port < 0 || sa.Port > 0xFFFF { 67 return nil, 0, EINVAL 68 } 69 sa.raw.Family = AF_INET 70 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 71 p[0] = byte(sa.Port >> 8) 72 p[1] = byte(sa.Port) 73 for i := 0; i < len(sa.Addr); i++ { 74 sa.raw.Addr[i] = sa.Addr[i] 75 } 76 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil 77} 78 79func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { 80 if sa.Port < 0 || sa.Port > 0xFFFF { 81 return nil, 0, EINVAL 82 } 83 sa.raw.Family = AF_INET6 84 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 85 p[0] = byte(sa.Port >> 8) 86 p[1] = byte(sa.Port) 87 sa.raw.Scope_id = sa.ZoneId 88 for i := 0; i < len(sa.Addr); i++ { 89 sa.raw.Addr[i] = sa.Addr[i] 90 } 91 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil 92} 93 94func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { 95 name := sa.Name 96 n := len(name) 97 if n > len(sa.raw.Path) { 98 return nil, 0, EINVAL 99 } 100 if n == len(sa.raw.Path) && name[0] != '@' { 101 return nil, 0, EINVAL 102 } 103 sa.raw.Family = AF_UNIX 104 for i := 0; i < n; i++ { 105 sa.raw.Path[i] = uint8(name[i]) 106 } 107 // length is family (uint16), name, NUL. 108 sl := _Socklen(2) 109 if n > 0 { 110 sl += _Socklen(n) + 1 111 } 112 if sa.raw.Path[0] == '@' { 113 sa.raw.Path[0] = 0 114 // Don't count trailing NUL for abstract address. 115 sl-- 116 } 117 118 return unsafe.Pointer(&sa.raw), sl, nil 119} 120 121func Getsockname(fd int) (sa Sockaddr, err error) { 122 var rsa RawSockaddrAny 123 var len _Socklen = SizeofSockaddrAny 124 if err = getsockname(fd, &rsa, &len); err != nil { 125 return 126 } 127 return anyToSockaddr(fd, &rsa) 128} 129 130//sys getcwd(buf []byte) (err error) 131 132const ImplementsGetwd = true 133 134func Getwd() (ret string, err error) { 135 for len := uint64(4096); ; len *= 2 { 136 b := make([]byte, len) 137 err := getcwd(b) 138 if err == nil { 139 i := 0 140 for b[i] != 0 { 141 i++ 142 } 143 return string(b[0:i]), nil 144 } 145 if err != ERANGE { 146 return "", err 147 } 148 } 149} 150 151func Getcwd(buf []byte) (n int, err error) { 152 err = getcwd(buf) 153 if err == nil { 154 i := 0 155 for buf[i] != 0 { 156 i++ 157 } 158 n = i + 1 159 } 160 return 161} 162 163func Getgroups() (gids []int, err error) { 164 n, err := getgroups(0, nil) 165 if err != nil { 166 return nil, err 167 } 168 if n == 0 { 169 return nil, nil 170 } 171 172 // Sanity check group count. Max is 16 on BSD. 173 if n < 0 || n > 1000 { 174 return nil, EINVAL 175 } 176 177 a := make([]_Gid_t, n) 178 n, err = getgroups(n, &a[0]) 179 if err != nil { 180 return nil, err 181 } 182 gids = make([]int, n) 183 for i, v := range a[0:n] { 184 gids[i] = int(v) 185 } 186 return 187} 188 189func Setgroups(gids []int) (err error) { 190 if len(gids) == 0 { 191 return setgroups(0, nil) 192 } 193 194 a := make([]_Gid_t, len(gids)) 195 for i, v := range gids { 196 a[i] = _Gid_t(v) 197 } 198 return setgroups(len(a), &a[0]) 199} 200 201/* 202 * Socket 203 */ 204 205//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) 206 207func Accept(fd int) (nfd int, sa Sockaddr, err error) { 208 var rsa RawSockaddrAny 209 var len _Socklen = SizeofSockaddrAny 210 nfd, err = accept(fd, &rsa, &len) 211 if nfd == -1 { 212 return 213 } 214 sa, err = anyToSockaddr(fd, &rsa) 215 if err != nil { 216 Close(nfd) 217 nfd = 0 218 } 219 return 220} 221 222func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { 223 // Recvmsg not implemented on AIX 224 sa := new(SockaddrUnix) 225 return -1, -1, -1, sa, ENOSYS 226} 227 228func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { 229 _, err = SendmsgN(fd, p, oob, to, flags) 230 return 231} 232 233func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { 234 // SendmsgN not implemented on AIX 235 return -1, ENOSYS 236} 237 238func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { 239 switch rsa.Addr.Family { 240 241 case AF_UNIX: 242 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) 243 sa := new(SockaddrUnix) 244 245 // Some versions of AIX have a bug in getsockname (see IV78655). 246 // We can't rely on sa.Len being set correctly. 247 n := SizeofSockaddrUnix - 3 // subtract leading Family, Len, terminating NUL. 248 for i := 0; i < n; i++ { 249 if pp.Path[i] == 0 { 250 n = i 251 break 252 } 253 } 254 255 bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] 256 sa.Name = string(bytes) 257 return sa, nil 258 259 case AF_INET: 260 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) 261 sa := new(SockaddrInet4) 262 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 263 sa.Port = int(p[0])<<8 + int(p[1]) 264 for i := 0; i < len(sa.Addr); i++ { 265 sa.Addr[i] = pp.Addr[i] 266 } 267 return sa, nil 268 269 case AF_INET6: 270 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) 271 sa := new(SockaddrInet6) 272 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 273 sa.Port = int(p[0])<<8 + int(p[1]) 274 sa.ZoneId = pp.Scope_id 275 for i := 0; i < len(sa.Addr); i++ { 276 sa.Addr[i] = pp.Addr[i] 277 } 278 return sa, nil 279 } 280 return nil, EAFNOSUPPORT 281} 282 283func Gettimeofday(tv *Timeval) (err error) { 284 err = gettimeofday(tv, nil) 285 return 286} 287 288func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { 289 if raceenabled { 290 raceReleaseMerge(unsafe.Pointer(&ioSync)) 291 } 292 return sendfile(outfd, infd, offset, count) 293} 294 295// TODO 296func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { 297 return -1, ENOSYS 298} 299 300func direntIno(buf []byte) (uint64, bool) { 301 return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino)) 302} 303 304func direntReclen(buf []byte) (uint64, bool) { 305 return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) 306} 307 308func direntNamlen(buf []byte) (uint64, bool) { 309 reclen, ok := direntReclen(buf) 310 if !ok { 311 return 0, false 312 } 313 return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true 314} 315 316//sys getdirent(fd int, buf []byte) (n int, err error) 317func Getdents(fd int, buf []byte) (n int, err error) { 318 return getdirent(fd, buf) 319} 320 321//sys wait4(pid Pid_t, status *_C_int, options int, rusage *Rusage) (wpid Pid_t, err error) 322func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { 323 var status _C_int 324 var r Pid_t 325 err = ERESTART 326 // AIX wait4 may return with ERESTART errno, while the processus is still 327 // active. 328 for err == ERESTART { 329 r, err = wait4(Pid_t(pid), &status, options, rusage) 330 } 331 wpid = int(r) 332 if wstatus != nil { 333 *wstatus = WaitStatus(status) 334 } 335 return 336} 337 338/* 339 * Wait 340 */ 341 342type WaitStatus uint32 343 344func (w WaitStatus) Stopped() bool { return w&0x40 != 0 } 345func (w WaitStatus) StopSignal() Signal { 346 if !w.Stopped() { 347 return -1 348 } 349 return Signal(w>>8) & 0xFF 350} 351 352func (w WaitStatus) Exited() bool { return w&0xFF == 0 } 353func (w WaitStatus) ExitStatus() int { 354 if !w.Exited() { 355 return -1 356 } 357 return int((w >> 8) & 0xFF) 358} 359 360func (w WaitStatus) Signaled() bool { return w&0x40 == 0 && w&0xFF != 0 } 361func (w WaitStatus) Signal() Signal { 362 if !w.Signaled() { 363 return -1 364 } 365 return Signal(w>>16) & 0xFF 366} 367 368func (w WaitStatus) Continued() bool { return w&0x01000000 != 0 } 369 370func (w WaitStatus) CoreDump() bool { return w&0x80 == 0x80 } 371 372func (w WaitStatus) TrapCause() int { return -1 } 373 374//sys ioctl(fd int, req uint, arg uintptr) (err error) 375 376// fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX 377// There is no way to create a custom fcntl and to keep //sys fcntl easily, 378// Therefore, the programmer must call dup2 instead of fcntl in this case. 379 380// FcntlInt performs a fcntl syscall on fd with the provided command and argument. 381//sys FcntlInt(fd uintptr, cmd int, arg int) (r int,err error) = fcntl 382 383// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command. 384//sys FcntlFlock(fd uintptr, cmd int, lk *Flock_t) (err error) = fcntl 385 386//sys fcntl(fd int, cmd int, arg int) (val int, err error) 387 388/* 389 * Direct access 390 */ 391 392//sys Acct(path string) (err error) 393//sys Chdir(path string) (err error) 394//sys Chroot(path string) (err error) 395//sys Close(fd int) (err error) 396//sys Dup(oldfd int) (fd int, err error) 397//sys Exit(code int) 398//sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error) 399//sys Fchdir(fd int) (err error) 400//sys Fchmod(fd int, mode uint32) (err error) 401//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) 402//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) 403//sys Fdatasync(fd int) (err error) 404//sys Fsync(fd int) (err error) 405// readdir_r 406//sysnb Getpgid(pid int) (pgid int, err error) 407 408//sys Getpgrp() (pid int) 409 410//sysnb Getpid() (pid int) 411//sysnb Getppid() (ppid int) 412//sys Getpriority(which int, who int) (prio int, err error) 413//sysnb Getrusage(who int, rusage *Rusage) (err error) 414//sysnb Getsid(pid int) (sid int, err error) 415//sysnb Kill(pid int, sig Signal) (err error) 416//sys Klogctl(typ int, buf []byte) (n int, err error) = syslog 417//sys Mkdir(dirfd int, path string, mode uint32) (err error) 418//sys Mkdirat(dirfd int, path string, mode uint32) (err error) 419//sys Mkfifo(path string, mode uint32) (err error) 420//sys Mknod(path string, mode uint32, dev int) (err error) 421//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) 422//sys Nanosleep(time *Timespec, leftover *Timespec) (err error) 423//sys Open(path string, mode int, perm uint32) (fd int, err error) = open64 424//sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) 425//sys read(fd int, p []byte) (n int, err error) 426//sys Readlink(path string, buf []byte) (n int, err error) 427//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) 428//sys Setdomainname(p []byte) (err error) 429//sys Sethostname(p []byte) (err error) 430//sysnb Setpgid(pid int, pgid int) (err error) 431//sysnb Setsid() (pid int, err error) 432//sysnb Settimeofday(tv *Timeval) (err error) 433 434//sys Setuid(uid int) (err error) 435//sys Setgid(uid int) (err error) 436 437//sys Setpriority(which int, who int, prio int) (err error) 438//sys Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) 439//sys Sync() 440//sysnb Times(tms *Tms) (ticks uintptr, err error) 441//sysnb Umask(mask int) (oldmask int) 442//sysnb Uname(buf *Utsname) (err error) 443//sys Unlink(path string) (err error) 444//sys Unlinkat(dirfd int, path string, flags int) (err error) 445//sys Ustat(dev int, ubuf *Ustat_t) (err error) 446//sys write(fd int, p []byte) (n int, err error) 447//sys readlen(fd int, p *byte, np int) (n int, err error) = read 448//sys writelen(fd int, p *byte, np int) (n int, err error) = write 449 450//sys Dup2(oldfd int, newfd int) (err error) 451//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = posix_fadvise64 452//sys Fchown(fd int, uid int, gid int) (err error) 453//sys fstat(fd int, stat *Stat_t) (err error) 454//sys fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = fstatat 455//sys Fstatfs(fd int, buf *Statfs_t) (err error) 456//sys Ftruncate(fd int, length int64) (err error) 457//sysnb Getegid() (egid int) 458//sysnb Geteuid() (euid int) 459//sysnb Getgid() (gid int) 460//sysnb Getuid() (uid int) 461//sys Lchown(path string, uid int, gid int) (err error) 462//sys Listen(s int, n int) (err error) 463//sys lstat(path string, stat *Stat_t) (err error) 464//sys Pause() (err error) 465//sys Pread(fd int, p []byte, offset int64) (n int, err error) = pread64 466//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = pwrite64 467//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) 468//sys Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) 469//sysnb Setregid(rgid int, egid int) (err error) 470//sysnb Setreuid(ruid int, euid int) (err error) 471//sys Shutdown(fd int, how int) (err error) 472//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) 473//sys stat(path string, statptr *Stat_t) (err error) 474//sys Statfs(path string, buf *Statfs_t) (err error) 475//sys Truncate(path string, length int64) (err error) 476 477//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) 478//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) 479//sysnb getgroups(n int, list *_Gid_t) (nn int, err error) 480//sysnb setgroups(n int, list *_Gid_t) (err error) 481//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) 482//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) 483//sysnb socket(domain int, typ int, proto int) (fd int, err error) 484//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) 485//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) 486//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) 487//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) 488//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) 489 490// In order to use msghdr structure with Control, Controllen, nrecvmsg and nsendmsg must be used. 491//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = nrecvmsg 492//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = nsendmsg 493 494//sys munmap(addr uintptr, length uintptr) (err error) 495 496var mapper = &mmapper{ 497 active: make(map[*byte][]byte), 498 mmap: mmap, 499 munmap: munmap, 500} 501 502func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { 503 return mapper.Mmap(fd, offset, length, prot, flags) 504} 505 506func Munmap(b []byte) (err error) { 507 return mapper.Munmap(b) 508} 509 510//sys Madvise(b []byte, advice int) (err error) 511//sys Mprotect(b []byte, prot int) (err error) 512//sys Mlock(b []byte) (err error) 513//sys Mlockall(flags int) (err error) 514//sys Msync(b []byte, flags int) (err error) 515//sys Munlock(b []byte) (err error) 516//sys Munlockall() (err error) 517 518//sysnb pipe(p *[2]_C_int) (err error) 519 520func Pipe(p []int) (err error) { 521 if len(p) != 2 { 522 return EINVAL 523 } 524 var pp [2]_C_int 525 err = pipe(&pp) 526 p[0] = int(pp[0]) 527 p[1] = int(pp[1]) 528 return 529} 530 531//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) 532 533func Poll(fds []PollFd, timeout int) (n int, err error) { 534 if len(fds) == 0 { 535 return poll(nil, 0, timeout) 536 } 537 return poll(&fds[0], len(fds), timeout) 538} 539 540//sys gettimeofday(tv *Timeval, tzp *Timezone) (err error) 541//sysnb Time(t *Time_t) (tt Time_t, err error) 542//sys Utime(path string, buf *Utimbuf) (err error) 543 544//sys Getsystemcfg(label int) (n uint64) 545 546//sys umount(target string) (err error) 547func Unmount(target string, flags int) (err error) { 548 if flags != 0 { 549 // AIX doesn't have any flags for umount. 550 return ENOSYS 551 } 552 return umount(target) 553} 554