syscall: add AIX operating system

This commit adds AIX operating system to syscall package for ppc64
architecture.
It also adds the file syscall_aix.go in the runtime package for
syscalls needed during fork and exec.

Updates: #25893

Change-Id: I301b1051b178a3efb7bbc39cdbd8e00b594d65ef
Reviewed-on: https://go-review.googlesource.com/c/138720
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Clément Chigot 2018-09-28 15:29:58 +02:00 committed by Ian Lance Taylor
parent c870d56f98
commit 8f9902da26
18 changed files with 3835 additions and 8 deletions

212
src/runtime/syscall_aix.go Normal file
View file

@ -0,0 +1,212 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package runtime
import "unsafe"
// This file handles some syscalls from the syscall package
// Especially, syscalls use during forkAndExecInChild which must not split the stack
//go:cgo_import_dynamic libc_chdir chdir "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_chroot chroot "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_dup2 dup2 "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_execve execve "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_fcntl fcntl "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_fork fork "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_ioctl ioctl "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setgid setgid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setgroups setgroups "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setsid setsid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setuid setuid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setpgid setpgid "libc.a/shr_64.o"
//go:linkname libc_chdir libc_chdir
//go:linkname libc_chroot libc_chroot
//go:linkname libc_dup2 libc_dup2
//go:linkname libc_execve libc_execve
//go:linkname libc_fcntl libc_fcntl
//go:linkname libc_fork libc_fork
//go:linkname libc_ioctl libc_ioctl
//go:linkname libc_setgid libc_setgid
//go:linkname libc_setgroups libc_setgroups
//go:linkname libc_setsid libc_setsid
//go:linkname libc_setuid libc_setuid
//go:linkname libc_setpgid libc_setpgid
var (
libc_chdir,
libc_chroot,
libc_dup2,
libc_execve,
libc_fcntl,
libc_fork,
libc_ioctl,
libc_setgid,
libc_setgroups,
libc_setsid,
libc_setuid,
libc_setpgid libFunc
)
// In syscall_syscall6 and syscall_rawsyscall6, r2 is always 0
// as it's never used on AIX
// TODO: remove r2 from zsyscall_aix_$GOARCH.go
// Syscall is needed because some packages (like net) need it too.
// The best way is to return EINVAL and let Golang handles its failure
// If the syscall can't fail, this function can redirect it to a real syscall.
//go:linkname syscall_Syscall syscall.Syscall
//go:nosplit
func syscall_Syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
return 0, 0, _EINVAL
}
// This is syscall.RawSyscall, it exists to satisfy some build dependency,
// but it doesn't work.
//go:linkname syscall_RawSyscall syscall.RawSyscall
func syscall_RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
panic("RawSyscall not available on AIX")
}
//go:linkname syscall_syscall6 syscall.syscall6
//go:nosplit
func syscall_syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
c := getg().m.libcall
c.fn = uintptr(unsafe.Pointer(fn))
c.n = nargs
c.args = uintptr(noescape(unsafe.Pointer(&a1)))
entersyscallblock()
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(&c))
exitsyscall()
return c.r1, 0, c.err
}
//go:linkname syscall_rawSyscall6 syscall.rawSyscall6
//go:nosplit
func syscall_rawSyscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
c := getg().m.libcall
c.fn = uintptr(unsafe.Pointer(fn))
c.n = nargs
c.args = uintptr(noescape(unsafe.Pointer(&a1)))
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(&c))
return c.r1, 0, c.err
}
//go:linkname syscall_chdir syscall.chdir
//go:nosplit
func syscall_chdir(path uintptr) (err uintptr) {
_, err = syscall1(&libc_chdir, path)
return
}
//go:linkname syscall_chroot1 syscall.chroot1
//go:nosplit
func syscall_chroot1(path uintptr) (err uintptr) {
_, err = syscall1(&libc_chroot, path)
return
}
// like close, but must not split stack, for fork.
//go:linkname syscall_close syscall.close
//go:nosplit
func syscall_close(fd int32) int32 {
_, err := syscall1(&libc_close, uintptr(fd))
return int32(err)
}
//go:linkname syscall_dup2child syscall.dup2child
//go:nosplit
func syscall_dup2child(old, new uintptr) (val, err uintptr) {
val, err = syscall2(&libc_dup2, old, new)
return
}
//go:linkname syscall_execve syscall.execve
//go:nosplit
func syscall_execve(path, argv, envp uintptr) (err uintptr) {
_, err = syscall3(&libc_execve, path, argv, envp)
return
}
// like exit, but must not split stack, for fork.
//go:linkname syscall_exit syscall.exit
//go:nosplit
func syscall_exit(code uintptr) {
syscall1(&libc_exit, code)
}
//go:linkname syscall_fcntl1 syscall.fcntl1
//go:nosplit
func syscall_fcntl1(fd, cmd, arg uintptr) (val, err uintptr) {
val, err = syscall3(&libc_fcntl, fd, cmd, arg)
return
}
//go:linkname syscall_forkx syscall.forkx
//go:nosplit
func syscall_forkx(flags uintptr) (pid uintptr, err uintptr) {
pid, err = syscall1(&libc_fork, flags)
return
}
//go:linkname syscall_getpid syscall.getpid
//go:nosplit
func syscall_getpid() (pid, err uintptr) {
pid, err = syscall0(&libc_getpid)
return
}
//go:linkname syscall_ioctl syscall.ioctl
//go:nosplit
func syscall_ioctl(fd, req, arg uintptr) (err uintptr) {
_, err = syscall3(&libc_ioctl, fd, req, arg)
return
}
//go:linkname syscall_setgid syscall.setgid
//go:nosplit
func syscall_setgid(gid uintptr) (err uintptr) {
_, err = syscall1(&libc_setgid, gid)
return
}
//go:linkname syscall_setgroups1 syscall.setgroups1
//go:nosplit
func syscall_setgroups1(ngid, gid uintptr) (err uintptr) {
_, err = syscall2(&libc_setgroups, ngid, gid)
return
}
//go:linkname syscall_setsid syscall.setsid
//go:nosplit
func syscall_setsid() (pid, err uintptr) {
pid, err = syscall0(&libc_setsid)
return
}
//go:linkname syscall_setuid syscall.setuid
//go:nosplit
func syscall_setuid(uid uintptr) (err uintptr) {
_, err = syscall1(&libc_setuid, uid)
return
}
//go:linkname syscall_setpgid syscall.setpgid
//go:nosplit
func syscall_setpgid(pid, pgid uintptr) (err uintptr) {
_, err = syscall2(&libc_setpgid, pid, pgid)
return
}
//go:linkname syscall_write1 syscall.write1
//go:nosplit
func syscall_write1(fd, buf, nbyte uintptr) (n, err uintptr) {
n, err = syscall3(&libc_write, fd, buf, nbyte)
return
}

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris // +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
package syscall package syscall

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris // +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
// Unix environment variables. // Unix environment variables.

View file

@ -0,0 +1,37 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix
package syscall
import "unsafe"
//go:cgo_import_dynamic libc_Getpgid getpgid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_Getpgrp getpgrp "libc.a/shr_64.o"
//go:linkname libc_Getpgid libc_Getpgid
//go:linkname libc_Getpgrp libc_Getpgrp
var (
libc_Getpgid,
libc_Getpgrp libcFunc
)
func Getpgid(pid int) (pgid int, err error) {
r0, _, e1 := syscall6(uintptr(unsafe.Pointer(&libc_Getpgid)), 1, uintptr(pid), 0, 0, 0, 0, 0)
pgid = int(r0)
if e1 != 0 {
err = e1
}
return
}
func Getpgrp() (pgrp int) {
r0, _, _ := syscall6(uintptr(unsafe.Pointer(&libc_Getpgrp)), 0, 0, 0, 0, 0, 0, 0)
pgrp = int(r0)
return
}
var Ioctl = ioctl

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package syscall_test package syscall_test

41
src/syscall/flock_aix.go Normal file
View file

@ -0,0 +1,41 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package syscall
import "unsafe"
// On AIX, there is no flock() system call, we emulate it.
// Moreover, we can't call the default fcntl syscall because the arguments
// must be integer and it's not possible to transform a pointer (lk)
// to a int value.
// It's easier to call syscall6 than to transform fcntl for every GOOS.
func fcntlFlock(fd, cmd int, lk *Flock_t) (err error) {
_, _, e1 := syscall6(uintptr(unsafe.Pointer(&libc_fcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
func Flock(fd int, op int) (err error) {
lk := &Flock_t{}
if (op & LOCK_UN) != 0 {
lk.Type = F_UNLCK
} else if (op & LOCK_EX) != 0 {
lk.Type = F_WRLCK
} else if (op & LOCK_SH) != 0 {
lk.Type = F_RDLCK
} else {
return nil
}
if (op & LOCK_NB) != 0 {
err = fcntlFlock(fd, F_SETLK, lk)
if err != nil && (err == EAGAIN || err == EACCES) {
return EWOULDBLOCK
}
return err
}
return fcntlFlock(fd, F_SETLKW, lk)
}

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly solaris // +build aix darwin dragonfly solaris
package syscall package syscall

View file

@ -20,6 +20,16 @@ fi
uname=$(uname) uname=$(uname)
includes_AIX='
#include <net/if.h>
#include <net/netopt.h>
#include <netinet/ip_mroute.h>
#include <sys/mman.h>
#include <sys/protosw.h>
#include <sys/ptrace.h>
#include <sys/stropts.h>
'
includes_Darwin=' includes_Darwin='
#define _DARWIN_C_SOURCE #define _DARWIN_C_SOURCE
#define KERNEL #define KERNEL

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd // +build aix darwin dragonfly freebsd linux netbsd openbsd
package syscall_test package syscall_test

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
// Socket control messages // Socket control messages

651
src/syscall/syscall_aix.go Normal file
View file

@ -0,0 +1,651 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Aix system calls.
// This file is compiled as ordinary Go code,
// but it is also input to mksyscall,
// which parses the //sys lines and generates system call stubs.
// Note that sometimes we use a lowercase //sys name and
// wrap it in our own nicer implementation.
package syscall
import (
"unsafe"
)
// Implemented in runtime/syscall_aix.go.
func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
// Constant expected by package but not supported
const (
_ = iota
TIOCSCTTY
F_DUPFD_CLOEXEC
SYS_EXECVE
SYS_FCNTL
)
/*
* Wrapped
*/
// fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX
// There is no way to create a custom fcntl and to keep //sys fcntl easily,
// because we need fcntl name for its libc symbol. This is linked with the script.
// But, as fcntl is currently not exported and isn't called with F_DUP2FD,
// it doesn't matter.
//sys fcntl(fd int, cmd int, arg int) (val int, err error)
//sys dup2(old int, new int) (val int, err error)
//sysnb pipe(p *[2]_C_int) (err error)
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe(&pp)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sys readlink(path string, buf []byte, bufSize uint64) (n int, err error)
func Readlink(path string, buf []byte) (n int, err error) {
s := uint64(len(buf))
return readlink(path, buf, s)
}
//sys utimes(path string, times *[2]Timeval) (err error)
func Utimes(path string, tv []Timeval) error {
if len(tv) != 2 {
return EINVAL
}
return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
}
//sys utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error)
func UtimesNano(path string, ts []Timespec) error {
if len(ts) != 2 {
return EINVAL
}
return utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
}
//sys unlinkat(dirfd int, path string, flags int) (err error)
func Unlinkat(dirfd int, path string) (err error) {
return unlinkat(dirfd, path, 0)
}
//sys getcwd(buf *byte, size uint64) (err error)
const ImplementsGetwd = true
func Getwd() (ret string, err error) {
for len := uint64(4096); ; len *= 2 {
b := make([]byte, len)
err := getcwd(&b[0], len)
if err == nil {
i := 0
for b[i] != 0 {
i++
}
return string(b[0:i]), nil
}
if err != ERANGE {
return "", err
}
}
}
func Getcwd(buf []byte) (n int, err error) {
err = getcwd(&buf[0], uint64(len(buf)))
if err == nil {
i := 0
for buf[i] != 0 {
i++
}
n = i + 1
}
return
}
//sysnb getgroups(ngid int, gid *_Gid_t) (n int, err error)
//sysnb setgroups(ngid int, gid *_Gid_t) (err error)
func Getgroups() (gids []int, err error) {
n, err := getgroups(0, nil)
if err != nil {
return nil, err
}
if n == 0 {
return nil, nil
}
// Sanity check group count. Max is 16 on BSD.
if n < 0 || n > 1000 {
return nil, EINVAL
}
a := make([]_Gid_t, n)
n, err = getgroups(n, &a[0])
if err != nil {
return nil, err
}
gids = make([]int, n)
for i, v := range a[0:n] {
gids[i] = int(v)
}
return
}
func Setgroups(gids []int) (err error) {
if len(gids) == 0 {
return setgroups(0, nil)
}
a := make([]_Gid_t, len(gids))
for i, v := range gids {
a[i] = _Gid_t(v)
}
return setgroups(len(a), &a[0])
}
func direntIno(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
}
func direntReclen(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
}
func direntNamlen(buf []byte) (uint64, bool) {
reclen, ok := direntReclen(buf)
if !ok {
return 0, false
}
return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
}
func Gettimeofday(tv *Timeval) (err error) {
err = gettimeofday(tv, nil)
return
}
// TODO
func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
return -1, ENOSYS
}
//sys getdirent(fd int, buf []byte) (n int, err error)
func ReadDirent(fd int, buf []byte) (n int, err error) {
return getdirent(fd, buf)
}
//sys wait4(pid Pid_t, status *_C_int, options int, rusage *Rusage) (wpid Pid_t, err error)
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
var status _C_int
var r Pid_t
err = ERESTART
// AIX wait4 may return with ERESTART errno, while the processus is still
// active.
for err == ERESTART {
r, err = wait4(Pid_t(pid), &status, options, rusage)
}
wpid = int(r)
if wstatus != nil {
*wstatus = WaitStatus(status)
}
return
}
/*
* Socket
*/
//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sys Getkerninfo(op int32, where uintptr, size uintptr, arg int64) (i int32, err error)
//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
//sys Listen(s int, backlog int) (err error)
//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
//sys socket(domain int, typ int, proto int) (fd int, err error)
//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sys getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
//sys Shutdown(s int, how int) (err error)
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
if sa.Port < 0 || sa.Port > 0xFFFF {
return nil, 0, EINVAL
}
sa.raw.Family = AF_INET
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
}
func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
if sa.Port < 0 || sa.Port > 0xFFFF {
return nil, 0, EINVAL
}
sa.raw.Family = AF_INET6
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
}
func (sa *RawSockaddrUnix) setLen(n int) {
sa.Len = uint8(3 + n) // 2 for Family, Len; 1 for NUL.
}
func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
name := sa.Name
n := len(name)
if n > len(sa.raw.Path) {
return nil, 0, EINVAL
}
sa.raw.Family = AF_UNIX
sa.raw.setLen(n)
for i := 0; i < n; i++ {
sa.raw.Path[i] = uint8(name[i])
}
// length is family (uint16), name, NUL.
sl := _Socklen(2)
if n > 0 {
sl += _Socklen(n) + 1
}
return unsafe.Pointer(&sa.raw), sl, nil
}
func Getsockname(fd int) (sa Sockaddr, err error) {
var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny
if err = getsockname(fd, &rsa, &len); err != nil {
return
}
return anyToSockaddr(&rsa)
}
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
func Accept(fd int) (nfd int, sa Sockaddr, err error) {
var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny
nfd, err = accept(fd, &rsa, &len)
if err != nil {
return
}
sa, err = anyToSockaddr(&rsa)
if err != nil {
Close(nfd)
nfd = 0
}
return
}
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
var msg Msghdr
var rsa RawSockaddrAny
msg.Name = (*byte)(unsafe.Pointer(&rsa))
msg.Namelen = uint32(SizeofSockaddrAny)
var iov Iovec
if len(p) > 0 {
iov.Base = (*byte)(unsafe.Pointer(&p[0]))
iov.SetLen(len(p))
}
var dummy byte
if len(oob) > 0 {
var sockType int
sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE)
if err != nil {
return
}
// receive at least one normal byte
if sockType != SOCK_DGRAM && len(p) == 0 {
iov.Base = &dummy
iov.SetLen(1)
}
msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
msg.SetControllen(len(oob))
}
msg.Iov = &iov
msg.Iovlen = 1
if n, err = recvmsg(fd, &msg, flags); err != nil {
return
}
oobn = int(msg.Controllen)
recvflags = int(msg.Flags)
// source address is only specified if the socket is unconnected
if rsa.Addr.Family != AF_UNSPEC {
from, err = anyToSockaddr(&rsa)
}
return
}
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
_, err = SendmsgN(fd, p, oob, to, flags)
return
}
func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
var ptr unsafe.Pointer
var salen _Socklen
if to != nil {
ptr, salen, err = to.sockaddr()
if err != nil {
return 0, err
}
}
var msg Msghdr
msg.Name = (*byte)(unsafe.Pointer(ptr))
msg.Namelen = uint32(salen)
var iov Iovec
if len(p) > 0 {
iov.Base = (*byte)(unsafe.Pointer(&p[0]))
iov.SetLen(len(p))
}
var dummy byte
if len(oob) > 0 {
var sockType int
sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE)
if err != nil {
return 0, err
}
// send at least one normal byte
if sockType != SOCK_DGRAM && len(p) == 0 {
iov.Base = &dummy
iov.SetLen(1)
}
msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
msg.SetControllen(len(oob))
}
msg.Iov = &iov
msg.Iovlen = 1
if n, err = sendmsg(fd, &msg, flags); err != nil {
return 0, err
}
if len(oob) > 0 && len(p) == 0 {
n = 0
}
return n, nil
}
func (sa *RawSockaddrUnix) getLen() (int, error) {
// Some versions of AIX have a bug in getsockname (see IV78655).
// We can't rely on sa.Len being set correctly.
n := SizeofSockaddrUnix - 3 // substract leading Family, Len, terminating NUL.
for i := 0; i < n; i++ {
if sa.Path[i] == 0 {
n = i
break
}
}
return n, nil
}
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
switch rsa.Addr.Family {
case AF_UNIX:
pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
sa := new(SockaddrUnix)
n, err := pp.getLen()
if err != nil {
return nil, err
}
bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))
sa.Name = string(bytes[0:n])
return sa, nil
case AF_INET:
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
return sa, nil
case AF_INET6:
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
sa := new(SockaddrInet6)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
return sa, nil
}
return nil, EAFNOSUPPORT
}
/*
* Wait
*/
type WaitStatus uint32
func (w WaitStatus) Stopped() bool { return w&0x40 != 0 }
func (w WaitStatus) StopSignal() Signal {
if !w.Stopped() {
return -1
}
return Signal(w>>8) & 0xFF
}
func (w WaitStatus) Exited() bool { return w&0xFF == 0 }
func (w WaitStatus) ExitStatus() int {
if !w.Exited() {
return -1
}
return int((w >> 8) & 0xFF)
}
func (w WaitStatus) Signaled() bool { return w&0x40 == 0 && w&0xFF != 0 }
func (w WaitStatus) Signal() Signal {
if !w.Signaled() {
return -1
}
return Signal(w>>16) & 0xFF
}
func (w WaitStatus) Continued() bool { return w&0x01000000 != 0 }
func (w WaitStatus) CoreDump() bool { return w&0x200 == 0 }
func (w WaitStatus) TrapCause() int { return -1 }
/*
* ptrace
*/
//sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
//sys ptrace64(request int, id int64, addr int64, data int, buff uintptr) (err error)
func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno {
if request == PTRACE_TRACEME {
// Convert to AIX ptrace call.
err := ptrace64(PT_TRACE_ME, 0, 0, 0, 0)
if err != nil {
return err.(Errno)
}
return 0
}
return ENOSYS
}
func ptracePeek(pid int, addr uintptr, out []byte) (count int, err error) {
n := 0
for len(out) > 0 {
bsize := len(out)
if bsize > 1024 {
bsize = 1024
}
err = ptrace64(PT_READ_BLOCK, int64(pid), int64(addr), bsize, uintptr(unsafe.Pointer(&out[0])))
if err != nil {
return 0, err
}
addr += uintptr(bsize)
n += bsize
out = out[n:]
}
return n, nil
}
func PtracePeekText(pid int, addr uintptr, out []byte) (count int, err error) {
return ptracePeek(pid, addr, out)
}
func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) {
return ptracePeek(pid, addr, out)
}
func ptracePoke(pid int, addr uintptr, data []byte) (count int, err error) {
n := 0
for len(data) > 0 {
bsize := len(data)
if bsize > 1024 {
bsize = 1024
}
err = ptrace64(PT_WRITE_BLOCK, int64(pid), int64(addr), bsize, uintptr(unsafe.Pointer(&data[0])))
if err != nil {
return 0, err
}
addr += uintptr(bsize)
n += bsize
data = data[n:]
}
return n, nil
}
func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) {
return ptracePoke(pid, addr, data)
}
func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) {
return ptracePoke(pid, addr, data)
}
func PtraceCont(pid int, signal int) (err error) {
return ptrace64(PT_CONTINUE, int64(pid), 1, signal, 0)
}
func PtraceSingleStep(pid int) (err error) { return ptrace64(PT_STEP, int64(pid), 1, 0, 0) }
func PtraceAttach(pid int) (err error) { return ptrace64(PT_ATTACH, int64(pid), 0, 0, 0) }
func PtraceDetach(pid int) (err error) { return ptrace64(PT_DETACH, int64(pid), 0, 0, 0) }
/*
* Direct access
*/
//sys Acct(path string) (err error)
//sys Chdir(path string) (err error)
//sys Chmod(path string, mode uint32) (err error)
//sys Chown(path string, uid int, gid int) (err error)
//sys Close(fd int) (err error)
//sys Dup(fd int) (nfd int, err error)
//sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
//sys Fchdir(fd int) (err error)
//sys Fchmod(fd int, mode uint32) (err error)
//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
//sys Fpathconf(fd int, name int) (val int, err error)
//sys Fstat(fd int, stat *Stat_t) (err error)
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
//sys Ftruncate(fd int, length int64) (err error)
//sys Fsync(fd int) (err error)
//sysnb Getgid() (gid int)
//sysnb Getpid() (pid int)
//sys Geteuid() (euid int)
//sys Getegid() (egid int)
//sys Getppid() (ppid int)
//sysnb Getrlimit(which int, lim *Rlimit) (err error)
//sysnb Getuid() (uid int)
//sys Kill(pid int, signum Signal) (err error)
//sys Lchown(path string, uid int, gid int) (err error)
//sys Link(path string, link string) (err error)
//sys Lstat(path string, stat *Stat_t) (err error)
//sys Mkdir(path string, mode uint32) (err error)
//sys Mkdirat(dirfd int, path string, mode uint32) (err error)
//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
//sys Open(path string, mode int, perm uint32) (fd int, err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error)
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
//sys read(fd int, p []byte) (n int, err error)
//sys Reboot(how int) (err error)
//sys Rename(from string, to string) (err error)
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys Rmdir(path string) (err error)
//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
//sysnb Setegid(egid int) (err error)
//sysnb Seteuid(euid int) (err error)
//sysnb Setgid(gid int) (err error)
//sysnb Setpgid(pid int, pgid int) (err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setreuid(ruid int, euid int) (err error)
//sys Stat(path string, stat *Stat_t) (err error)
//sys Statfs(path string, buf *Statfs_t) (err error)
//sys Symlink(path string, link string) (err error)
//sys Truncate(path string, length int64) (err error)
//sys Umask(newmask int) (oldmask int)
//sys Unlink(path string) (err error)
//sysnb Uname(buf *Utsname) (err error)
//sys write(fd int, p []byte) (n int, err error)
//sys gettimeofday(tv *Timeval, tzp *Timezone) (err error)
func setTimespec(sec, nsec int64) Timespec {
return Timespec{Sec: sec, Nsec: nsec}
}
func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: sec, Usec: int32(usec)}
}
func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
r0, _, e1 := syscall6(uintptr(unsafe.Pointer(&libc_read)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
n = int(r0)
if e1 != 0 {
err = e1
}
return
}
/*
* Map
*/
var mapper = &mmapper{
active: make(map[*byte][]byte),
mmap: mmap,
munmap: munmap,
}
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
//sys munmap(addr uintptr, length uintptr) (err error)
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
return mapper.Mmap(fd, offset, length, prot, flags)
}
func Munmap(b []byte) (err error) {
return mapper.Munmap(b)
}

View file

@ -0,0 +1,17 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package syscall
func (iov *Iovec) SetLen(length int) {
iov.Len = uint64(length)
}
func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package syscall package syscall

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris // +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
package syscall package syscall

172
src/syscall/types_aix.go Normal file
View file

@ -0,0 +1,172 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
Input to cgo -godefs. See also mkerrors.sh and mkall.sh
*/
// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
package syscall
/*
#include <sys/types.h>
#include <sys/time.h>
#include <sys/limits.h>
#include <sys/un.h>
#include <sys/utsname.h>
#include <sys/ptrace.h>
#include <sys/statfs.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/icmp6.h>
#include <dirent.h>
#include <fcntl.h>
#include <gcrypt.h>
enum {
sizeofPtr = sizeof(void*),
};
union sockaddr_all {
struct sockaddr s1; // this one gets used for fields
struct sockaddr_in s2; // these pad it out
struct sockaddr_in6 s3;
struct sockaddr_un s4;
};
struct sockaddr_any {
struct sockaddr addr;
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
};
*/
import "C"
// Machine characteristics; for internal use.
const (
sizeofPtr = C.sizeofPtr
sizeofShort = C.sizeof_short
sizeofInt = C.sizeof_int
sizeofLong = C.sizeof_long
sizeofLongLong = C.sizeof_longlong
PathMax = C.PATH_MAX
)
// Basic types
type (
_C_short C.short
_C_int C.int
_C_long C.long
_C_long_long C.longlong
)
// Time
type Timespec C.struct_timespec
type Timeval C.struct_timeval
type Timeval32 C.struct_timeval32
type Timezone C.struct_timezone
// Processes
type Rusage C.struct_rusage
type Rlimit C.struct_rlimit
type Pid_t C.pid_t
type _Gid_t C.gid_t
// Files
type Flock_t C.struct_flock
type Stat_t C.struct_stat
type Statfs_t C.struct_statfs
type Fsid64_t C.fsid64_t
type StTimespec_t C.st_timespec_t
type Dirent C.struct_dirent
// Sockets
type RawSockaddrInet4 C.struct_sockaddr_in
type RawSockaddrInet6 C.struct_sockaddr_in6
type RawSockaddrUnix C.struct_sockaddr_un
type RawSockaddr C.struct_sockaddr
type RawSockaddrAny C.struct_sockaddr_any
type _Socklen C.socklen_t
type Cmsghdr C.struct_cmsghdr
type ICMPv6Filter C.struct_icmp6_filter
type Iovec C.struct_iovec
type IPMreq C.struct_ip_mreq
type IPv6Mreq C.struct_ipv6_mreq
type Linger C.struct_linger
type Msghdr C.struct_msghdr
const (
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
SizeofLinger = C.sizeof_struct_linger
SizeofIPMreq = C.sizeof_struct_ip_mreq
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
SizeofMsghdr = C.sizeof_struct_msghdr
SizeofCmsghdr = C.sizeof_struct_cmsghdr
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
)
// Ptrace requests
const (
PTRACE_TRACEME = C.PT_TRACE_ME
PTRACE_CONT = C.PT_CONTINUE
PTRACE_KILL = C.PT_KILL
)
// Routing and interface messages
const (
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
)
type IfMsgHdr C.struct_if_msghdr
// Misc
type Utsname C.struct_utsname
const (
_AT_FDCWD = C.AT_FDCWD
_AT_REMOVEDIR = C.AT_REMOVEDIR
_AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,272 @@
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs types_aix.go | go run mkpost.go
package syscall
const (
sizeofPtr = 0x8
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
PathMax = 0x3ff
)
type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
)
type Timespec struct {
Sec int64
Nsec int64
}
type Timeval struct {
Sec int64
Usec int32
Pad_cgo_0 [4]byte
}
type Timeval32 struct {
Sec int32
Usec int32
}
type Timezone struct {
Minuteswest int32
Dsttime int32
}
type Rusage struct {
Utime Timeval
Stime Timeval
Maxrss int64
Ixrss int64
Idrss int64
Isrss int64
Minflt int64
Majflt int64
Nswap int64
Inblock int64
Oublock int64
Msgsnd int64
Msgrcv int64
Nsignals int64
Nvcsw int64
Nivcsw int64
}
type Rlimit struct {
Cur uint64
Max uint64
}
type Pid_t int32
type _Gid_t uint32
type Flock_t struct {
Type int16
Whence int16
Sysid uint32
Pid int32
Vfs int32
Start int64
Len int64
}
type Stat_t struct {
Dev uint64
Ino uint64
Mode uint32
Nlink int16
Flag uint16
Uid uint32
Gid uint32
Rdev uint64
Ssize int32
Pad_cgo_0 [4]byte
Atim StTimespec_t
Mtim StTimespec_t
Ctim StTimespec_t
Blksize int64
Blocks int64
Vfstype int32
Vfs uint32
Type uint32
Gen uint32
Reserved [9]uint32
Padto_ll uint32
Size int64
}
type Statfs_t struct {
Version int32
Type int32
Bsize uint64
Blocks uint64
Bfree uint64
Bavail uint64
Files uint64
Ffree uint64
Fsid Fsid64_t
Vfstype int32
Pad_cgo_0 [4]byte
Fsize uint64
Vfsnumber int32
Vfsoff int32
Vfslen int32
Vfsvers int32
Fname [32]uint8
Fpack [32]uint8
Name_max int32
Pad_cgo_1 [4]byte
}
type Fsid64_t struct {
Val [2]uint64
}
type StTimespec_t struct {
Sec int64
Nsec int32
Pad_cgo_0 [4]byte
}
type Dirent struct {
Offset uint64
Ino uint64
Reclen uint16
Namlen uint16
Name [256]uint8
Pad_cgo_0 [4]byte
}
type RawSockaddrInet4 struct {
Len uint8
Family uint8
Port uint16
Addr [4]byte /* in_addr */
Zero [8]uint8
}
type RawSockaddrInet6 struct {
Len uint8
Family uint8
Port uint16
Flowinfo uint32
Addr [16]byte /* in6_addr */
Scope_id uint32
}
type RawSockaddrUnix struct {
Len uint8
Family uint8
Path [1023]uint8
}
type RawSockaddr struct {
Len uint8
Family uint8
Data [14]uint8
}
type RawSockaddrAny struct {
Addr RawSockaddr
Pad [1012]uint8
}
type _Socklen uint32
type Cmsghdr struct {
Len uint32
Level int32
Type int32
}
type ICMPv6Filter struct {
Filt [8]uint32
}
type Iovec struct {
Base *byte
Len uint64
}
type IPMreq struct {
Multiaddr [4]byte /* in_addr */
Interface [4]byte /* in_addr */
}
type IPv6Mreq struct {
Multiaddr [16]byte /* in6_addr */
Interface uint32
}
type Linger struct {
Onoff int32
Linger int32
}
type Msghdr struct {
Name *byte
Namelen uint32
Pad_cgo_0 [4]byte
Iov *Iovec
Iovlen int32
Pad_cgo_1 [4]byte
Control *byte
Controllen uint32
Flags int32
}
const (
SizeofSockaddrInet4 = 0x10
SizeofSockaddrInet6 = 0x1c
SizeofSockaddrAny = 0x404
SizeofSockaddrUnix = 0x401
SizeofLinger = 0x8
SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14
SizeofMsghdr = 0x30
SizeofCmsghdr = 0xc
SizeofICMPv6Filter = 0x20
)
const (
PTRACE_TRACEME = 0x0
PTRACE_CONT = 0x7
PTRACE_KILL = 0x8
)
const (
SizeofIfMsghdr = 0x10
)
type IfMsgHdr struct {
Msglen uint16
Version uint8
Type uint8
Addrs int32
Flags int32
Index uint16
Addrlen uint8
Pad_cgo_0 [1]byte
}
type Utsname struct {
Sysname [32]uint8
Nodename [32]uint8
Release [32]uint8
Version [32]uint8
Machine [32]uint8
}
const (
_AT_FDCWD = -0x2
_AT_REMOVEDIR = 0x1
_AT_SYMLINK_NOFOLLOW = 0x1
)