// Copyright 2009 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.

// Linux 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 unix

import (
	
	
	
	
	
)

/*
 * Wrapped
 */

func ( string,  uint32) ( error) {
	return Faccessat(AT_FDCWD, , , 0)
}

func ( string,  uint32) ( error) {
	return Fchmodat(AT_FDCWD, , , 0)
}

func ( string,  int,  int) ( error) {
	return Fchownat(AT_FDCWD, , , , 0)
}

func ( string,  uint32) ( int,  error) {
	return Open(, O_CREAT|O_WRONLY|O_TRUNC, )
}

func ( int) ( int,  error) {
	if  <= 0 {
		return -1, EINVAL
	}
	return EpollCreate1(0)
}

//sys	FanotifyInit(flags uint, event_f_flags uint) (fd int, err error)
//sys	fanotifyMark(fd int, flags uint, mask uint64, dirFd int, pathname *byte) (err error)

func ( int,  uint,  uint64,  int,  string) ( error) {
	if  == "" {
		return fanotifyMark(, , , , nil)
	}
	,  := BytePtrFromString()
	if  != nil {
		return 
	}
	return fanotifyMark(, , , , )
}

//sys	fchmodat(dirfd int, path string, mode uint32) (err error)

func ( int,  string,  uint32,  int) ( error) {
	// Linux fchmodat doesn't support the flags parameter. Mimick glibc's behavior
	// and check the flags. Otherwise the mode would be applied to the symlink
	// destination which is not what the user expects.
	if &^AT_SYMLINK_NOFOLLOW != 0 {
		return EINVAL
	} else if &AT_SYMLINK_NOFOLLOW != 0 {
		return EOPNOTSUPP
	}
	return fchmodat(, , )
}

func () ( int,  error) {
	return InotifyInit1(0)
}

//sys	ioctl(fd int, req uint, arg uintptr) (err error) = SYS_IOCTL
//sys	ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL

// ioctl itself should not be exposed directly, but additional get/set functions
// for specific types are permissible. These are defined in ioctl.go and
// ioctl_linux.go.
//
// The third argument to ioctl is often a pointer but sometimes an integer.
// Callers should use ioctlPtr when the third argument is a pointer and ioctl
// when the third argument is an integer.
//
// TODO: some existing code incorrectly uses ioctl when it should use ioctlPtr.

//sys	Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error)

func ( string,  string) ( error) {
	return Linkat(AT_FDCWD, , AT_FDCWD, , 0)
}

func ( string,  uint32) ( error) {
	return Mkdirat(AT_FDCWD, , )
}

func ( string,  uint32,  int) ( error) {
	return Mknodat(AT_FDCWD, , , )
}

func ( string,  int,  uint32) ( int,  error) {
	return openat(AT_FDCWD, , |O_LARGEFILE, )
}

//sys	openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)

func ( int,  string,  int,  uint32) ( int,  error) {
	return openat(, , |O_LARGEFILE, )
}

//sys	openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error)

func ( int,  string,  *OpenHow) ( int,  error) {
	return openat2(, , , SizeofOpenHow)
}

func ( []int) error {
	return Pipe2(, 0)
}

//sysnb	pipe2(p *[2]_C_int, flags int) (err error)

func ( []int,  int) error {
	if len() != 2 {
		return EINVAL
	}
	var  [2]_C_int
	 := pipe2(&, )
	if  == nil {
		[0] = int([0])
		[1] = int([1])
	}
	return 
}

//sys	ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error)

func ( []PollFd,  *Timespec,  *Sigset_t) ( int,  error) {
	if len() == 0 {
		return ppoll(nil, 0, , )
	}
	return ppoll(&[0], len(), , )
}

func ( []PollFd,  int) ( int,  error) {
	var  *Timespec
	if  >= 0 {
		 = new(Timespec)
		* = NsecToTimespec(int64() * 1e6)
	}
	return Ppoll(, , nil)
}

//sys	Readlinkat(dirfd int, path string, buf []byte) (n int, err error)

func ( string,  []byte) ( int,  error) {
	return Readlinkat(AT_FDCWD, , )
}

func ( string,  string) ( error) {
	return Renameat(AT_FDCWD, , AT_FDCWD, )
}

func ( string) error {
	return Unlinkat(AT_FDCWD, , AT_REMOVEDIR)
}

//sys	Symlinkat(oldpath string, newdirfd int, newpath string) (err error)

func ( string,  string) ( error) {
	return Symlinkat(, AT_FDCWD, )
}

func ( string) error {
	return Unlinkat(AT_FDCWD, , 0)
}

//sys	Unlinkat(dirfd int, path string, flags int) (err error)

func ( string,  []Timeval) error {
	if  == nil {
		 := utimensat(AT_FDCWD, , nil, 0)
		if  != ENOSYS {
			return 
		}
		return utimes(, nil)
	}
	if len() != 2 {
		return EINVAL
	}
	var  [2]Timespec
	[0] = NsecToTimespec(TimevalToNsec([0]))
	[1] = NsecToTimespec(TimevalToNsec([1]))
	 := utimensat(AT_FDCWD, , (*[2]Timespec)(unsafe.Pointer(&[0])), 0)
	if  != ENOSYS {
		return 
	}
	return utimes(, (*[2]Timeval)(unsafe.Pointer(&[0])))
}

//sys	utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error)

func ( string,  []Timespec) error {
	return UtimesNanoAt(AT_FDCWD, , , 0)
}

func ( int,  string,  []Timespec,  int) error {
	if  == nil {
		return utimensat(, , nil, )
	}
	if len() != 2 {
		return EINVAL
	}
	return utimensat(, , (*[2]Timespec)(unsafe.Pointer(&[0])), )
}

func ( int,  string,  []Timeval) error {
	if  == nil {
		return futimesat(, , nil)
	}
	if len() != 2 {
		return EINVAL
	}
	return futimesat(, , (*[2]Timeval)(unsafe.Pointer(&[0])))
}

func ( int,  []Timeval) ( error) {
	// Believe it or not, this is the best we can do on Linux
	// (and is what glibc does).
	return Utimes("/proc/self/fd/"+strconv.Itoa(), )
}

const ImplementsGetwd = true

//sys	Getcwd(buf []byte) (n int, err error)

func () ( string,  error) {
	var  [PathMax]byte
	,  := Getcwd([0:])
	if  != nil {
		return "", 
	}
	// Getcwd returns the number of bytes written to buf, including the NUL.
	if  < 1 ||  > len() || [-1] != 0 {
		return "", EINVAL
	}
	// In some cases, Linux can return a path that starts with the
	// "(unreachable)" prefix, which can potentially be a valid relative
	// path. To work around that, return ENOENT if path is not absolute.
	if [0] != '/' {
		return "", ENOENT
	}

	return string([0 : -1]), nil
}

func () ( []int,  error) {
	,  := getgroups(0, nil)
	if  != nil {
		return nil, 
	}
	if  == 0 {
		return nil, nil
	}

	// Sanity check group count. Max is 1<<16 on Linux.
	if  < 0 ||  > 1<<20 {
		return nil, EINVAL
	}

	 := make([]_Gid_t, )
	,  = getgroups(, &[0])
	if  != nil {
		return nil, 
	}
	 = make([]int, )
	for ,  := range [0:] {
		[] = int()
	}
	return
}

func ( []int) ( error) {
	if len() == 0 {
		return setgroups(0, nil)
	}

	 := make([]_Gid_t, len())
	for ,  := range  {
		[] = _Gid_t()
	}
	return setgroups(len(), &[0])
}

type WaitStatus uint32

// Wait status is 7 bits at bottom, either 0 (exited),
// 0x7F (stopped), or a signal number that caused an exit.
// The 0x80 bit is whether there was a core dump.
// An extra number (exit code, signal causing a stop)
// is in the high bits. At least that's the idea.
// There are various irregularities. For example, the
// "continued" status is 0xFFFF, distinguishing itself
// from stopped via the core dump bit.

const (
	mask    = 0x7F
	core    = 0x80
	exited  = 0x00
	stopped = 0x7F
	shift   = 8
)

func ( WaitStatus) () bool { return &mask == exited }

func ( WaitStatus) () bool { return &mask != stopped && &mask != exited }

func ( WaitStatus) () bool { return &0xFF == stopped }

func ( WaitStatus) () bool { return  == 0xFFFF }

func ( WaitStatus) () bool { return .Signaled() && &core != 0 }

func ( WaitStatus) () int {
	if !.Exited() {
		return -1
	}
	return int(>>shift) & 0xFF
}

func ( WaitStatus) () syscall.Signal {
	if !.Signaled() {
		return -1
	}
	return syscall.Signal( & mask)
}

func ( WaitStatus) () syscall.Signal {
	if !.Stopped() {
		return -1
	}
	return syscall.Signal(>>shift) & 0xFF
}

func ( WaitStatus) () int {
	if .StopSignal() != SIGTRAP {
		return -1
	}
	return int(>>shift) >> 8
}

//sys	wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error)

func ( int,  *WaitStatus,  int,  *Rusage) ( int,  error) {
	var  _C_int
	,  = wait4(, &, , )
	if  != nil {
		* = WaitStatus()
	}
	return
}

//sys	Waitid(idType int, id int, info *Siginfo, options int, rusage *Rusage) (err error)

func ( string,  uint32) error {
	return Mknod(, |S_IFIFO, 0)
}

func ( int,  string,  uint32) error {
	return Mknodat(, , |S_IFIFO, 0)
}

func ( *SockaddrInet4) () (unsafe.Pointer, _Socklen, error) {
	if .Port < 0 || .Port > 0xFFFF {
		return nil, 0, EINVAL
	}
	.raw.Family = AF_INET
	 := (*[2]byte)(unsafe.Pointer(&.raw.Port))
	[0] = byte(.Port >> 8)
	[1] = byte(.Port)
	.raw.Addr = .Addr
	return unsafe.Pointer(&.raw), SizeofSockaddrInet4, nil
}

func ( *SockaddrInet6) () (unsafe.Pointer, _Socklen, error) {
	if .Port < 0 || .Port > 0xFFFF {
		return nil, 0, EINVAL
	}
	.raw.Family = AF_INET6
	 := (*[2]byte)(unsafe.Pointer(&.raw.Port))
	[0] = byte(.Port >> 8)
	[1] = byte(.Port)
	.raw.Scope_id = .ZoneId
	.raw.Addr = .Addr
	return unsafe.Pointer(&.raw), SizeofSockaddrInet6, nil
}

func ( *SockaddrUnix) () (unsafe.Pointer, _Socklen, error) {
	 := .Name
	 := len()
	if  >= len(.raw.Path) {
		return nil, 0, EINVAL
	}
	.raw.Family = AF_UNIX
	for  := 0;  < ; ++ {
		.raw.Path[] = int8([])
	}
	// length is family (uint16), name, NUL.
	 := _Socklen(2)
	if  > 0 {
		 += _Socklen() + 1
	}
	if .raw.Path[0] == '@' {
		.raw.Path[0] = 0
		// Don't count trailing NUL for abstract address.
		--
	}

	return unsafe.Pointer(&.raw), , nil
}

// SockaddrLinklayer implements the Sockaddr interface for AF_PACKET type sockets.
type SockaddrLinklayer struct {
	Protocol uint16
	Ifindex  int
	Hatype   uint16
	Pkttype  uint8
	Halen    uint8
	Addr     [8]byte
	raw      RawSockaddrLinklayer
}

func ( *SockaddrLinklayer) () (unsafe.Pointer, _Socklen, error) {
	if .Ifindex < 0 || .Ifindex > 0x7fffffff {
		return nil, 0, EINVAL
	}
	.raw.Family = AF_PACKET
	.raw.Protocol = .Protocol
	.raw.Ifindex = int32(.Ifindex)
	.raw.Hatype = .Hatype
	.raw.Pkttype = .Pkttype
	.raw.Halen = .Halen
	.raw.Addr = .Addr
	return unsafe.Pointer(&.raw), SizeofSockaddrLinklayer, nil
}

// SockaddrNetlink implements the Sockaddr interface for AF_NETLINK type sockets.
type SockaddrNetlink struct {
	Family uint16
	Pad    uint16
	Pid    uint32
	Groups uint32
	raw    RawSockaddrNetlink
}

func ( *SockaddrNetlink) () (unsafe.Pointer, _Socklen, error) {
	.raw.Family = AF_NETLINK
	.raw.Pad = .Pad
	.raw.Pid = .Pid
	.raw.Groups = .Groups
	return unsafe.Pointer(&.raw), SizeofSockaddrNetlink, nil
}

// SockaddrHCI implements the Sockaddr interface for AF_BLUETOOTH type sockets
// using the HCI protocol.
type SockaddrHCI struct {
	Dev     uint16
	Channel uint16
	raw     RawSockaddrHCI
}

func ( *SockaddrHCI) () (unsafe.Pointer, _Socklen, error) {
	.raw.Family = AF_BLUETOOTH
	.raw.Dev = .Dev
	.raw.Channel = .Channel
	return unsafe.Pointer(&.raw), SizeofSockaddrHCI, nil
}

// SockaddrL2 implements the Sockaddr interface for AF_BLUETOOTH type sockets
// using the L2CAP protocol.
type SockaddrL2 struct {
	PSM      uint16
	CID      uint16
	Addr     [6]uint8
	AddrType uint8
	raw      RawSockaddrL2
}

func ( *SockaddrL2) () (unsafe.Pointer, _Socklen, error) {
	.raw.Family = AF_BLUETOOTH
	 := (*[2]byte)(unsafe.Pointer(&.raw.Psm))
	[0] = byte(.PSM)
	[1] = byte(.PSM >> 8)
	for  := 0;  < len(.Addr); ++ {
		.raw.Bdaddr[] = .Addr[len(.Addr)-1-]
	}
	 := (*[2]byte)(unsafe.Pointer(&.raw.Cid))
	[0] = byte(.CID)
	[1] = byte(.CID >> 8)
	.raw.Bdaddr_type = .AddrType
	return unsafe.Pointer(&.raw), SizeofSockaddrL2, nil
}

// SockaddrRFCOMM implements the Sockaddr interface for AF_BLUETOOTH type sockets
// using the RFCOMM protocol.
//
// Server example:
//
//	fd, _ := Socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)
//	_ = unix.Bind(fd, &unix.SockaddrRFCOMM{
//		Channel: 1,
//		Addr:    [6]uint8{0, 0, 0, 0, 0, 0}, // BDADDR_ANY or 00:00:00:00:00:00
//	})
//	_ = Listen(fd, 1)
//	nfd, sa, _ := Accept(fd)
//	fmt.Printf("conn addr=%v fd=%d", sa.(*unix.SockaddrRFCOMM).Addr, nfd)
//	Read(nfd, buf)
//
// Client example:
//
//	fd, _ := Socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)
//	_ = Connect(fd, &SockaddrRFCOMM{
//		Channel: 1,
//		Addr:    [6]byte{0x11, 0x22, 0x33, 0xaa, 0xbb, 0xcc}, // CC:BB:AA:33:22:11
//	})
//	Write(fd, []byte(`hello`))
type SockaddrRFCOMM struct {
	// Addr represents a bluetooth address, byte ordering is little-endian.
	Addr [6]uint8

	// Channel is a designated bluetooth channel, only 1-30 are available for use.
	// Since Linux 2.6.7 and further zero value is the first available channel.
	Channel uint8

	raw RawSockaddrRFCOMM
}

func ( *SockaddrRFCOMM) () (unsafe.Pointer, _Socklen, error) {
	.raw.Family = AF_BLUETOOTH
	.raw.Channel = .Channel
	.raw.Bdaddr = .Addr
	return unsafe.Pointer(&.raw), SizeofSockaddrRFCOMM, nil
}

// SockaddrCAN implements the Sockaddr interface for AF_CAN type sockets.
// The RxID and TxID fields are used for transport protocol addressing in
// (CAN_TP16, CAN_TP20, CAN_MCNET, and CAN_ISOTP), they can be left with
// zero values for CAN_RAW and CAN_BCM sockets as they have no meaning.
//
// The SockaddrCAN struct must be bound to the socket file descriptor
// using Bind before the CAN socket can be used.
//
//	// Read one raw CAN frame
//	fd, _ := Socket(AF_CAN, SOCK_RAW, CAN_RAW)
//	addr := &SockaddrCAN{Ifindex: index}
//	Bind(fd, addr)
//	frame := make([]byte, 16)
//	Read(fd, frame)
//
// The full SocketCAN documentation can be found in the linux kernel
// archives at: https://www.kernel.org/doc/Documentation/networking/can.txt
type SockaddrCAN struct {
	Ifindex int
	RxID    uint32
	TxID    uint32
	raw     RawSockaddrCAN
}

func ( *SockaddrCAN) () (unsafe.Pointer, _Socklen, error) {
	if .Ifindex < 0 || .Ifindex > 0x7fffffff {
		return nil, 0, EINVAL
	}
	.raw.Family = AF_CAN
	.raw.Ifindex = int32(.Ifindex)
	 := (*[4]byte)(unsafe.Pointer(&.RxID))
	for  := 0;  < 4; ++ {
		.raw.Addr[] = []
	}
	 := (*[4]byte)(unsafe.Pointer(&.TxID))
	for  := 0;  < 4; ++ {
		.raw.Addr[+4] = []
	}
	return unsafe.Pointer(&.raw), SizeofSockaddrCAN, nil
}

// SockaddrCANJ1939 implements the Sockaddr interface for AF_CAN using J1939
// protocol (https://en.wikipedia.org/wiki/SAE_J1939). For more information
// on the purposes of the fields, check the official linux kernel documentation
// available here: https://www.kernel.org/doc/Documentation/networking/j1939.rst
type SockaddrCANJ1939 struct {
	Ifindex int
	Name    uint64
	PGN     uint32
	Addr    uint8
	raw     RawSockaddrCAN
}

func ( *SockaddrCANJ1939) () (unsafe.Pointer, _Socklen, error) {
	if .Ifindex < 0 || .Ifindex > 0x7fffffff {
		return nil, 0, EINVAL
	}
	.raw.Family = AF_CAN
	.raw.Ifindex = int32(.Ifindex)
	 := (*[8]byte)(unsafe.Pointer(&.Name))
	for  := 0;  < 8; ++ {
		.raw.Addr[] = []
	}
	 := (*[4]byte)(unsafe.Pointer(&.PGN))
	for  := 0;  < 4; ++ {
		.raw.Addr[+8] = []
	}
	.raw.Addr[12] = .Addr
	return unsafe.Pointer(&.raw), SizeofSockaddrCAN, nil
}

// SockaddrALG implements the Sockaddr interface for AF_ALG type sockets.
// SockaddrALG enables userspace access to the Linux kernel's cryptography
// subsystem. The Type and Name fields specify which type of hash or cipher
// should be used with a given socket.
//
// To create a file descriptor that provides access to a hash or cipher, both
// Bind and Accept must be used. Once the setup process is complete, input
// data can be written to the socket, processed by the kernel, and then read
// back as hash output or ciphertext.
//
// Here is an example of using an AF_ALG socket with SHA1 hashing.
// The initial socket setup process is as follows:
//
//	// Open a socket to perform SHA1 hashing.
//	fd, _ := unix.Socket(unix.AF_ALG, unix.SOCK_SEQPACKET, 0)
//	addr := &unix.SockaddrALG{Type: "hash", Name: "sha1"}
//	unix.Bind(fd, addr)
//	// Note: unix.Accept does not work at this time; must invoke accept()
//	// manually using unix.Syscall.
//	hashfd, _, _ := unix.Syscall(unix.SYS_ACCEPT, uintptr(fd), 0, 0)
//
// Once a file descriptor has been returned from Accept, it may be used to
// perform SHA1 hashing. The descriptor is not safe for concurrent use, but
// may be re-used repeatedly with subsequent Write and Read operations.
//
// When hashing a small byte slice or string, a single Write and Read may
// be used:
//
//	// Assume hashfd is already configured using the setup process.
//	hash := os.NewFile(hashfd, "sha1")
//	// Hash an input string and read the results. Each Write discards
//	// previous hash state. Read always reads the current state.
//	b := make([]byte, 20)
//	for i := 0; i < 2; i++ {
//	    io.WriteString(hash, "Hello, world.")
//	    hash.Read(b)
//	    fmt.Println(hex.EncodeToString(b))
//	}
//	// Output:
//	// 2ae01472317d1935a84797ec1983ae243fc6aa28
//	// 2ae01472317d1935a84797ec1983ae243fc6aa28
//
// For hashing larger byte slices, or byte streams such as those read from
// a file or socket, use Sendto with MSG_MORE to instruct the kernel to update
// the hash digest instead of creating a new one for a given chunk and finalizing it.
//
//	// Assume hashfd and addr are already configured using the setup process.
//	hash := os.NewFile(hashfd, "sha1")
//	// Hash the contents of a file.
//	f, _ := os.Open("/tmp/linux-4.10-rc7.tar.xz")
//	b := make([]byte, 4096)
//	for {
//	    n, err := f.Read(b)
//	    if err == io.EOF {
//	        break
//	    }
//	    unix.Sendto(hashfd, b[:n], unix.MSG_MORE, addr)
//	}
//	hash.Read(b)
//	fmt.Println(hex.EncodeToString(b))
//	// Output: 85cdcad0c06eef66f805ecce353bec9accbeecc5
//
// For more information, see: http://www.chronox.de/crypto-API/crypto/userspace-if.html.
type SockaddrALG struct {
	Type    string
	Name    string
	Feature uint32
	Mask    uint32
	raw     RawSockaddrALG
}

func ( *SockaddrALG) () (unsafe.Pointer, _Socklen, error) {
	// Leave room for NUL byte terminator.
	if len(.Type) > len(.raw.Type)-1 {
		return nil, 0, EINVAL
	}
	if len(.Name) > len(.raw.Name)-1 {
		return nil, 0, EINVAL
	}

	.raw.Family = AF_ALG
	.raw.Feat = .Feature
	.raw.Mask = .Mask

	copy(.raw.Type[:], .Type)
	copy(.raw.Name[:], .Name)

	return unsafe.Pointer(&.raw), SizeofSockaddrALG, nil
}

// SockaddrVM implements the Sockaddr interface for AF_VSOCK type sockets.
// SockaddrVM provides access to Linux VM sockets: a mechanism that enables
// bidirectional communication between a hypervisor and its guest virtual
// machines.
type SockaddrVM struct {
	// CID and Port specify a context ID and port address for a VM socket.
	// Guests have a unique CID, and hosts may have a well-known CID of:
	//  - VMADDR_CID_HYPERVISOR: refers to the hypervisor process.
	//  - VMADDR_CID_LOCAL: refers to local communication (loopback).
	//  - VMADDR_CID_HOST: refers to other processes on the host.
	CID   uint32
	Port  uint32
	Flags uint8
	raw   RawSockaddrVM
}

func ( *SockaddrVM) () (unsafe.Pointer, _Socklen, error) {
	.raw.Family = AF_VSOCK
	.raw.Port = .Port
	.raw.Cid = .CID
	.raw.Flags = .Flags

	return unsafe.Pointer(&.raw), SizeofSockaddrVM, nil
}

type SockaddrXDP struct {
	Flags        uint16
	Ifindex      uint32
	QueueID      uint32
	SharedUmemFD uint32
	raw          RawSockaddrXDP
}

func ( *SockaddrXDP) () (unsafe.Pointer, _Socklen, error) {
	.raw.Family = AF_XDP
	.raw.Flags = .Flags
	.raw.Ifindex = .Ifindex
	.raw.Queue_id = .QueueID
	.raw.Shared_umem_fd = .SharedUmemFD

	return unsafe.Pointer(&.raw), SizeofSockaddrXDP, nil
}

// This constant mirrors the #define of PX_PROTO_OE in
// linux/if_pppox.h. We're defining this by hand here instead of
// autogenerating through mkerrors.sh because including
// linux/if_pppox.h causes some declaration conflicts with other
// includes (linux/if_pppox.h includes linux/in.h, which conflicts
// with netinet/in.h). Given that we only need a single zero constant
// out of that file, it's cleaner to just define it by hand here.
const px_proto_oe = 0

type SockaddrPPPoE struct {
	SID    uint16
	Remote []byte
	Dev    string
	raw    RawSockaddrPPPoX
}

func ( *SockaddrPPPoE) () (unsafe.Pointer, _Socklen, error) {
	if len(.Remote) != 6 {
		return nil, 0, EINVAL
	}
	if len(.Dev) > IFNAMSIZ-1 {
		return nil, 0, EINVAL
	}

	*(*uint16)(unsafe.Pointer(&.raw[0])) = AF_PPPOX
	// This next field is in host-endian byte order. We can't use the
	// same unsafe pointer cast as above, because this value is not
	// 32-bit aligned and some architectures don't allow unaligned
	// access.
	//
	// However, the value of px_proto_oe is 0, so we can use
	// encoding/binary helpers to write the bytes without worrying
	// about the ordering.
	binary.BigEndian.PutUint32(.raw[2:6], px_proto_oe)
	// This field is deliberately big-endian, unlike the previous
	// one. The kernel expects SID to be in network byte order.
	binary.BigEndian.PutUint16(.raw[6:8], .SID)
	copy(.raw[8:14], .Remote)
	for  := 14;  < 14+IFNAMSIZ; ++ {
		.raw[] = 0
	}
	copy(.raw[14:], .Dev)
	return unsafe.Pointer(&.raw), SizeofSockaddrPPPoX, nil
}

// SockaddrTIPC implements the Sockaddr interface for AF_TIPC type sockets.
// For more information on TIPC, see: http://tipc.sourceforge.net/.
type SockaddrTIPC struct {
	// Scope is the publication scopes when binding service/service range.
	// Should be set to TIPC_CLUSTER_SCOPE or TIPC_NODE_SCOPE.
	Scope int

	// Addr is the type of address used to manipulate a socket. Addr must be
	// one of:
	//  - *TIPCSocketAddr: "id" variant in the C addr union
	//  - *TIPCServiceRange: "nameseq" variant in the C addr union
	//  - *TIPCServiceName: "name" variant in the C addr union
	//
	// If nil, EINVAL will be returned when the structure is used.
	Addr TIPCAddr

	raw RawSockaddrTIPC
}

// TIPCAddr is implemented by types that can be used as an address for
// SockaddrTIPC. It is only implemented by *TIPCSocketAddr, *TIPCServiceRange,
// and *TIPCServiceName.
type TIPCAddr interface {
	tipcAddrtype() uint8
	tipcAddr() [12]byte
}

func ( *TIPCSocketAddr) () [12]byte {
	var  [12]byte
	copy([:], (*(*[unsafe.Sizeof(TIPCSocketAddr{})]byte)(unsafe.Pointer()))[:])
	return 
}

func ( *TIPCSocketAddr) () uint8 { return TIPC_SOCKET_ADDR }

func ( *TIPCServiceRange) () [12]byte {
	var  [12]byte
	copy([:], (*(*[unsafe.Sizeof(TIPCServiceRange{})]byte)(unsafe.Pointer()))[:])
	return 
}

func ( *TIPCServiceRange) () uint8 { return TIPC_SERVICE_RANGE }

func ( *TIPCServiceName) () [12]byte {
	var  [12]byte
	copy([:], (*(*[unsafe.Sizeof(TIPCServiceName{})]byte)(unsafe.Pointer()))[:])
	return 
}

func ( *TIPCServiceName) () uint8 { return TIPC_SERVICE_ADDR }

func ( *SockaddrTIPC) () (unsafe.Pointer, _Socklen, error) {
	if .Addr == nil {
		return nil, 0, EINVAL
	}
	.raw.Family = AF_TIPC
	.raw.Scope = int8(.Scope)
	.raw.Addrtype = .Addr.tipcAddrtype()
	.raw.Addr = .Addr.tipcAddr()
	return unsafe.Pointer(&.raw), SizeofSockaddrTIPC, nil
}

// SockaddrL2TPIP implements the Sockaddr interface for IPPROTO_L2TP/AF_INET sockets.
type SockaddrL2TPIP struct {
	Addr   [4]byte
	ConnId uint32
	raw    RawSockaddrL2TPIP
}

func ( *SockaddrL2TPIP) () (unsafe.Pointer, _Socklen, error) {
	.raw.Family = AF_INET
	.raw.Conn_id = .ConnId
	.raw.Addr = .Addr
	return unsafe.Pointer(&.raw), SizeofSockaddrL2TPIP, nil
}

// SockaddrL2TPIP6 implements the Sockaddr interface for IPPROTO_L2TP/AF_INET6 sockets.
type SockaddrL2TPIP6 struct {
	Addr   [16]byte
	ZoneId uint32
	ConnId uint32
	raw    RawSockaddrL2TPIP6
}

func ( *SockaddrL2TPIP6) () (unsafe.Pointer, _Socklen, error) {
	.raw.Family = AF_INET6
	.raw.Conn_id = .ConnId
	.raw.Scope_id = .ZoneId
	.raw.Addr = .Addr
	return unsafe.Pointer(&.raw), SizeofSockaddrL2TPIP6, nil
}

// SockaddrIUCV implements the Sockaddr interface for AF_IUCV sockets.
type SockaddrIUCV struct {
	UserID string
	Name   string
	raw    RawSockaddrIUCV
}

func ( *SockaddrIUCV) () (unsafe.Pointer, _Socklen, error) {
	.raw.Family = AF_IUCV
	// These are EBCDIC encoded by the kernel, but we still need to pad them
	// with blanks. Initializing with blanks allows the caller to feed in either
	// a padded or an unpadded string.
	for  := 0;  < 8; ++ {
		.raw.Nodeid[] = ' '
		.raw.User_id[] = ' '
		.raw.Name[] = ' '
	}
	if len(.UserID) > 8 || len(.Name) > 8 {
		return nil, 0, EINVAL
	}
	for ,  := range []byte(.UserID[:]) {
		.raw.User_id[] = int8()
	}
	for ,  := range []byte(.Name[:]) {
		.raw.Name[] = int8()
	}
	return unsafe.Pointer(&.raw), SizeofSockaddrIUCV, nil
}

type SockaddrNFC struct {
	DeviceIdx   uint32
	TargetIdx   uint32
	NFCProtocol uint32
	raw         RawSockaddrNFC
}

func ( *SockaddrNFC) () (unsafe.Pointer, _Socklen, error) {
	.raw.Sa_family = AF_NFC
	.raw.Dev_idx = .DeviceIdx
	.raw.Target_idx = .TargetIdx
	.raw.Nfc_protocol = .NFCProtocol
	return unsafe.Pointer(&.raw), SizeofSockaddrNFC, nil
}

type SockaddrNFCLLCP struct {
	DeviceIdx      uint32
	TargetIdx      uint32
	NFCProtocol    uint32
	DestinationSAP uint8
	SourceSAP      uint8
	ServiceName    string
	raw            RawSockaddrNFCLLCP
}

func ( *SockaddrNFCLLCP) () (unsafe.Pointer, _Socklen, error) {
	.raw.Sa_family = AF_NFC
	.raw.Dev_idx = .DeviceIdx
	.raw.Target_idx = .TargetIdx
	.raw.Nfc_protocol = .NFCProtocol
	.raw.Dsap = .DestinationSAP
	.raw.Ssap = .SourceSAP
	if len(.ServiceName) > len(.raw.Service_name) {
		return nil, 0, EINVAL
	}
	copy(.raw.Service_name[:], .ServiceName)
	.raw.SetServiceNameLen(len(.ServiceName))
	return unsafe.Pointer(&.raw), SizeofSockaddrNFCLLCP, nil
}

var socketProtocol = func( int) (int, error) {
	return GetsockoptInt(, SOL_SOCKET, SO_PROTOCOL)
}

func anyToSockaddr( int,  *RawSockaddrAny) (Sockaddr, error) {
	switch .Addr.Family {
	case AF_NETLINK:
		 := (*RawSockaddrNetlink)(unsafe.Pointer())
		 := new(SockaddrNetlink)
		.Family = .Family
		.Pad = .Pad
		.Pid = .Pid
		.Groups = .Groups
		return , nil

	case AF_PACKET:
		 := (*RawSockaddrLinklayer)(unsafe.Pointer())
		 := new(SockaddrLinklayer)
		.Protocol = .Protocol
		.Ifindex = int(.Ifindex)
		.Hatype = .Hatype
		.Pkttype = .Pkttype
		.Halen = .Halen
		.Addr = .Addr
		return , nil

	case AF_UNIX:
		 := (*RawSockaddrUnix)(unsafe.Pointer())
		 := new(SockaddrUnix)
		if .Path[0] == 0 {
			// "Abstract" Unix domain socket.
			// Rewrite leading NUL as @ for textual display.
			// (This is the standard convention.)
			// Not friendly to overwrite in place,
			// but the callers below don't care.
			.Path[0] = '@'
		}

		// Assume path ends at NUL.
		// This is not technically the Linux semantics for
		// abstract Unix domain sockets--they are supposed
		// to be uninterpreted fixed-size binary blobs--but
		// everyone uses this convention.
		 := 0
		for  < len(.Path) && .Path[] != 0 {
			++
		}
		.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&.Path[0])), ))
		return , nil

	case AF_INET:
		,  := socketProtocol()
		if  != nil {
			return nil, 
		}

		switch  {
		case IPPROTO_L2TP:
			 := (*RawSockaddrL2TPIP)(unsafe.Pointer())
			 := new(SockaddrL2TPIP)
			.ConnId = .Conn_id
			.Addr = .Addr
			return , nil
		default:
			 := (*RawSockaddrInet4)(unsafe.Pointer())
			 := new(SockaddrInet4)
			 := (*[2]byte)(unsafe.Pointer(&.Port))
			.Port = int([0])<<8 + int([1])
			.Addr = .Addr
			return , nil
		}

	case AF_INET6:
		,  := socketProtocol()
		if  != nil {
			return nil, 
		}

		switch  {
		case IPPROTO_L2TP:
			 := (*RawSockaddrL2TPIP6)(unsafe.Pointer())
			 := new(SockaddrL2TPIP6)
			.ConnId = .Conn_id
			.ZoneId = .Scope_id
			.Addr = .Addr
			return , nil
		default:
			 := (*RawSockaddrInet6)(unsafe.Pointer())
			 := new(SockaddrInet6)
			 := (*[2]byte)(unsafe.Pointer(&.Port))
			.Port = int([0])<<8 + int([1])
			.ZoneId = .Scope_id
			.Addr = .Addr
			return , nil
		}

	case AF_VSOCK:
		 := (*RawSockaddrVM)(unsafe.Pointer())
		 := &SockaddrVM{
			CID:   .Cid,
			Port:  .Port,
			Flags: .Flags,
		}
		return , nil
	case AF_BLUETOOTH:
		,  := socketProtocol()
		if  != nil {
			return nil, 
		}
		// only BTPROTO_L2CAP and BTPROTO_RFCOMM can accept connections
		switch  {
		case BTPROTO_L2CAP:
			 := (*RawSockaddrL2)(unsafe.Pointer())
			 := &SockaddrL2{
				PSM:      .Psm,
				CID:      .Cid,
				Addr:     .Bdaddr,
				AddrType: .Bdaddr_type,
			}
			return , nil
		case BTPROTO_RFCOMM:
			 := (*RawSockaddrRFCOMM)(unsafe.Pointer())
			 := &SockaddrRFCOMM{
				Channel: .Channel,
				Addr:    .Bdaddr,
			}
			return , nil
		}
	case AF_XDP:
		 := (*RawSockaddrXDP)(unsafe.Pointer())
		 := &SockaddrXDP{
			Flags:        .Flags,
			Ifindex:      .Ifindex,
			QueueID:      .Queue_id,
			SharedUmemFD: .Shared_umem_fd,
		}
		return , nil
	case AF_PPPOX:
		 := (*RawSockaddrPPPoX)(unsafe.Pointer())
		if binary.BigEndian.Uint32([2:6]) != px_proto_oe {
			return nil, EINVAL
		}
		 := &SockaddrPPPoE{
			SID:    binary.BigEndian.Uint16([6:8]),
			Remote: [8:14],
		}
		for  := 14;  < 14+IFNAMSIZ; ++ {
			if [] == 0 {
				.Dev = string([14:])
				break
			}
		}
		return , nil
	case AF_TIPC:
		 := (*RawSockaddrTIPC)(unsafe.Pointer())

		 := &SockaddrTIPC{
			Scope: int(.Scope),
		}

		// Determine which union variant is present in pp.Addr by checking
		// pp.Addrtype.
		switch .Addrtype {
		case TIPC_SERVICE_RANGE:
			.Addr = (*TIPCServiceRange)(unsafe.Pointer(&.Addr))
		case TIPC_SERVICE_ADDR:
			.Addr = (*TIPCServiceName)(unsafe.Pointer(&.Addr))
		case TIPC_SOCKET_ADDR:
			.Addr = (*TIPCSocketAddr)(unsafe.Pointer(&.Addr))
		default:
			return nil, EINVAL
		}

		return , nil
	case AF_IUCV:
		 := (*RawSockaddrIUCV)(unsafe.Pointer())

		var  [8]byte
		var  [8]byte

		for  := 0;  < 8; ++ {
			[] = byte(.User_id[])
			[] = byte(.Name[])
		}

		 := &SockaddrIUCV{
			UserID: string([:]),
			Name:   string([:]),
		}
		return , nil

	case AF_CAN:
		,  := socketProtocol()
		if  != nil {
			return nil, 
		}

		 := (*RawSockaddrCAN)(unsafe.Pointer())

		switch  {
		case CAN_J1939:
			 := &SockaddrCANJ1939{
				Ifindex: int(.Ifindex),
			}
			 := (*[8]byte)(unsafe.Pointer(&.Name))
			for  := 0;  < 8; ++ {
				[] = .Addr[]
			}
			 := (*[4]byte)(unsafe.Pointer(&.PGN))
			for  := 0;  < 4; ++ {
				[] = .Addr[+8]
			}
			 := (*[1]byte)(unsafe.Pointer(&.Addr))
			[0] = .Addr[12]
			return , nil
		default:
			 := &SockaddrCAN{
				Ifindex: int(.Ifindex),
			}
			 := (*[4]byte)(unsafe.Pointer(&.RxID))
			for  := 0;  < 4; ++ {
				[] = .Addr[]
			}
			 := (*[4]byte)(unsafe.Pointer(&.TxID))
			for  := 0;  < 4; ++ {
				[] = .Addr[+4]
			}
			return , nil
		}
	case AF_NFC:
		,  := socketProtocol()
		if  != nil {
			return nil, 
		}
		switch  {
		case NFC_SOCKPROTO_RAW:
			 := (*RawSockaddrNFC)(unsafe.Pointer())
			 := &SockaddrNFC{
				DeviceIdx:   .Dev_idx,
				TargetIdx:   .Target_idx,
				NFCProtocol: .Nfc_protocol,
			}
			return , nil
		case NFC_SOCKPROTO_LLCP:
			 := (*RawSockaddrNFCLLCP)(unsafe.Pointer())
			if uint64(.Service_name_len) > uint64(len(.Service_name)) {
				return nil, EINVAL
			}
			 := &SockaddrNFCLLCP{
				DeviceIdx:      .Dev_idx,
				TargetIdx:      .Target_idx,
				NFCProtocol:    .Nfc_protocol,
				DestinationSAP: .Dsap,
				SourceSAP:      .Ssap,
				ServiceName:    string(.Service_name[:.Service_name_len]),
			}
			return , nil
		default:
			return nil, EINVAL
		}
	}
	return nil, EAFNOSUPPORT
}

func ( int) ( int,  Sockaddr,  error) {
	var  RawSockaddrAny
	var  _Socklen = SizeofSockaddrAny
	,  = accept4(, &, &, 0)
	if  != nil {
		return
	}
	,  = anyToSockaddr(, &)
	if  != nil {
		Close()
		 = 0
	}
	return
}

func ( int,  int) ( int,  Sockaddr,  error) {
	var  RawSockaddrAny
	var  _Socklen = SizeofSockaddrAny
	,  = accept4(, &, &, )
	if  != nil {
		return
	}
	if  > SizeofSockaddrAny {
		panic("RawSockaddrAny too small")
	}
	,  = anyToSockaddr(, &)
	if  != nil {
		Close()
		 = 0
	}
	return
}

func ( int) ( Sockaddr,  error) {
	var  RawSockaddrAny
	var  _Socklen = SizeofSockaddrAny
	if  = getsockname(, &, &);  != nil {
		return
	}
	return anyToSockaddr(, &)
}

func (, ,  int) (*IPMreqn, error) {
	var  IPMreqn
	 := _Socklen(SizeofIPMreqn)
	 := getsockopt(, , , unsafe.Pointer(&), &)
	return &, 
}

func (, ,  int) (*Ucred, error) {
	var  Ucred
	 := _Socklen(SizeofUcred)
	 := getsockopt(, , , unsafe.Pointer(&), &)
	return &, 
}

func (, ,  int) (*TCPInfo, error) {
	var  TCPInfo
	 := _Socklen(SizeofTCPInfo)
	 := getsockopt(, , , unsafe.Pointer(&), &)
	return &, 
}

// GetsockoptString returns the string value of the socket option opt for the
// socket associated with fd at the given socket level.
func (, ,  int) (string, error) {
	 := make([]byte, 256)
	 := _Socklen(len())
	 := getsockopt(, , , unsafe.Pointer(&[0]), &)
	if  != nil {
		if  == ERANGE {
			 = make([]byte, )
			 = getsockopt(, , , unsafe.Pointer(&[0]), &)
		}
		if  != nil {
			return "", 
		}
	}
	return string([:-1]), nil
}

func (, ,  int) (*TpacketStats, error) {
	var  TpacketStats
	 := _Socklen(SizeofTpacketStats)
	 := getsockopt(, , , unsafe.Pointer(&), &)
	return &, 
}

func (, ,  int) (*TpacketStatsV3, error) {
	var  TpacketStatsV3
	 := _Socklen(SizeofTpacketStatsV3)
	 := getsockopt(, , , unsafe.Pointer(&), &)
	return &, 
}

func (, ,  int,  *IPMreqn) ( error) {
	return setsockopt(, , , unsafe.Pointer(), unsafe.Sizeof(*))
}

func (, ,  int,  *PacketMreq) error {
	return setsockopt(, , , unsafe.Pointer(), unsafe.Sizeof(*))
}

// SetsockoptSockFprog attaches a classic BPF or an extended BPF program to a
// socket to filter incoming packets.  See 'man 7 socket' for usage information.
func (, ,  int,  *SockFprog) error {
	return setsockopt(, , , unsafe.Pointer(), unsafe.Sizeof(*))
}

func (, ,  int,  []CanFilter) error {
	var  unsafe.Pointer
	if len() > 0 {
		 = unsafe.Pointer(&[0])
	}
	return setsockopt(, , , , uintptr(len()*SizeofCanFilter))
}

func (, ,  int,  *TpacketReq) error {
	return setsockopt(, , , unsafe.Pointer(), unsafe.Sizeof(*))
}

func (, ,  int,  *TpacketReq3) error {
	return setsockopt(, , , unsafe.Pointer(), unsafe.Sizeof(*))
}

func (, ,  int,  []TCPRepairOpt) ( error) {
	if len() == 0 {
		return EINVAL
	}
	return setsockopt(, , , unsafe.Pointer(&[0]), uintptr(SizeofTCPRepairOpt*len()))
}

func (, ,  int,  *TCPMD5Sig) error {
	return setsockopt(, , , unsafe.Pointer(), unsafe.Sizeof(*))
}

// Keyctl Commands (http://man7.org/linux/man-pages/man2/keyctl.2.html)

// KeyctlInt calls keyctl commands in which each argument is an int.
// These commands are KEYCTL_REVOKE, KEYCTL_CHOWN, KEYCTL_CLEAR, KEYCTL_LINK,
// KEYCTL_UNLINK, KEYCTL_NEGATE, KEYCTL_SET_REQKEY_KEYRING, KEYCTL_SET_TIMEOUT,
// KEYCTL_ASSUME_AUTHORITY, KEYCTL_SESSION_TO_PARENT, KEYCTL_REJECT,
// KEYCTL_INVALIDATE, and KEYCTL_GET_PERSISTENT.
//sys	KeyctlInt(cmd int, arg2 int, arg3 int, arg4 int, arg5 int) (ret int, err error) = SYS_KEYCTL

// KeyctlBuffer calls keyctl commands in which the third and fourth
// arguments are a buffer and its length, respectively.
// These commands are KEYCTL_UPDATE, KEYCTL_READ, and KEYCTL_INSTANTIATE.
//sys	KeyctlBuffer(cmd int, arg2 int, buf []byte, arg5 int) (ret int, err error) = SYS_KEYCTL

// KeyctlString calls keyctl commands which return a string.
// These commands are KEYCTL_DESCRIBE and KEYCTL_GET_SECURITY.
func ( int,  int) (string, error) {
	// We must loop as the string data may change in between the syscalls.
	// We could allocate a large buffer here to reduce the chance that the
	// syscall needs to be called twice; however, this is unnecessary as
	// the performance loss is negligible.
	var  []byte
	for {
		// Try to fill the buffer with data
		,  := KeyctlBuffer(, , , 0)
		if  != nil {
			return "", 
		}

		// Check if the data was written
		if  <= len() {
			// Exclude the null terminator
			return string([:-1]), nil
		}

		// Make a bigger buffer if needed
		 = make([]byte, )
	}
}

// Keyctl commands with special signatures.

// KeyctlGetKeyringID implements the KEYCTL_GET_KEYRING_ID command.
// See the full documentation at:
// http://man7.org/linux/man-pages/man3/keyctl_get_keyring_ID.3.html
func ( int,  bool) ( int,  error) {
	 := 0
	if  {
		 = 1
	}
	return KeyctlInt(KEYCTL_GET_KEYRING_ID, , , 0, 0)
}

// KeyctlSetperm implements the KEYCTL_SETPERM command. The perm value is the
// key handle permission mask as described in the "keyctl setperm" section of
// http://man7.org/linux/man-pages/man1/keyctl.1.html.
// See the full documentation at:
// http://man7.org/linux/man-pages/man3/keyctl_setperm.3.html
func ( int,  uint32) error {
	,  := KeyctlInt(KEYCTL_SETPERM, , int(), 0, 0)
	return 
}

//sys	keyctlJoin(cmd int, arg2 string) (ret int, err error) = SYS_KEYCTL

// KeyctlJoinSessionKeyring implements the KEYCTL_JOIN_SESSION_KEYRING command.
// See the full documentation at:
// http://man7.org/linux/man-pages/man3/keyctl_join_session_keyring.3.html
func ( string) ( int,  error) {
	return keyctlJoin(KEYCTL_JOIN_SESSION_KEYRING, )
}

//sys	keyctlSearch(cmd int, arg2 int, arg3 string, arg4 string, arg5 int) (ret int, err error) = SYS_KEYCTL

// KeyctlSearch implements the KEYCTL_SEARCH command.
// See the full documentation at:
// http://man7.org/linux/man-pages/man3/keyctl_search.3.html
func ( int, ,  string,  int) ( int,  error) {
	return keyctlSearch(KEYCTL_SEARCH, , , , )
}

//sys	keyctlIOV(cmd int, arg2 int, payload []Iovec, arg5 int) (err error) = SYS_KEYCTL

// KeyctlInstantiateIOV implements the KEYCTL_INSTANTIATE_IOV command. This
// command is similar to KEYCTL_INSTANTIATE, except that the payload is a slice
// of Iovec (each of which represents a buffer) instead of a single buffer.
// See the full documentation at:
// http://man7.org/linux/man-pages/man3/keyctl_instantiate_iov.3.html
func ( int,  []Iovec,  int) error {
	return keyctlIOV(KEYCTL_INSTANTIATE_IOV, , , )
}

//sys	keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) = SYS_KEYCTL

// KeyctlDHCompute implements the KEYCTL_DH_COMPUTE command. This command
// computes a Diffie-Hellman shared secret based on the provide params. The
// secret is written to the provided buffer and the returned size is the number
// of bytes written (returning an error if there is insufficient space in the
// buffer). If a nil buffer is passed in, this function returns the minimum
// buffer length needed to store the appropriate data. Note that this differs
// from KEYCTL_READ's behavior which always returns the requested payload size.
// See the full documentation at:
// http://man7.org/linux/man-pages/man3/keyctl_dh_compute.3.html
func ( *KeyctlDHParams,  []byte) ( int,  error) {
	return keyctlDH(KEYCTL_DH_COMPUTE, , )
}

// KeyctlRestrictKeyring implements the KEYCTL_RESTRICT_KEYRING command. This
// command limits the set of keys that can be linked to the keyring, regardless
// of keyring permissions. The command requires the "setattr" permission.
//
// When called with an empty keyType the command locks the keyring, preventing
// any further keys from being linked to the keyring.
//
// The "asymmetric" keyType defines restrictions requiring key payloads to be
// DER encoded X.509 certificates signed by keys in another keyring. Restrictions
// for "asymmetric" include "builtin_trusted", "builtin_and_secondary_trusted",
// "key_or_keyring:<key>", and "key_or_keyring:<key>:chain".
//
// As of Linux 4.12, only the "asymmetric" keyType defines type-specific
// restrictions.
//
// See the full documentation at:
// http://man7.org/linux/man-pages/man3/keyctl_restrict_keyring.3.html
// http://man7.org/linux/man-pages/man2/keyctl.2.html
func ( int,  string,  string) error {
	if  == "" {
		return keyctlRestrictKeyring(KEYCTL_RESTRICT_KEYRING, )
	}
	return keyctlRestrictKeyringByType(KEYCTL_RESTRICT_KEYRING, , , )
}

//sys	keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) = SYS_KEYCTL
//sys	keyctlRestrictKeyring(cmd int, arg2 int) (err error) = SYS_KEYCTL

func recvmsgRaw( int,  []Iovec,  []byte,  int,  *RawSockaddrAny) (,  int,  int,  error) {
	var  Msghdr
	.Name = (*byte)(unsafe.Pointer())
	.Namelen = uint32(SizeofSockaddrAny)
	var  byte
	if len() > 0 {
		if emptyIovecs() {
			var  int
			,  = GetsockoptInt(, SOL_SOCKET, SO_TYPE)
			if  != nil {
				return
			}
			// receive at least one normal byte
			if  != SOCK_DGRAM {
				var  [1]Iovec
				[0].Base = &
				[0].SetLen(1)
				 = [:]
			}
		}
		.Control = &[0]
		.SetControllen(len())
	}
	if len() > 0 {
		.Iov = &[0]
		.SetIovlen(len())
	}
	if ,  = recvmsg(, &, );  != nil {
		return
	}
	 = int(.Controllen)
	 = int(.Flags)
	return
}

func sendmsgN( int,  []Iovec,  []byte,  unsafe.Pointer,  _Socklen,  int) ( int,  error) {
	var  Msghdr
	.Name = (*byte)()
	.Namelen = uint32()
	var  byte
	var  bool
	if len() > 0 {
		 = emptyIovecs()
		if  {
			var  int
			,  = GetsockoptInt(, SOL_SOCKET, SO_TYPE)
			if  != nil {
				return 0, 
			}
			// send at least one normal byte
			if  != SOCK_DGRAM {
				var  [1]Iovec
				[0].Base = &
				[0].SetLen(1)
				 = [:]
			}
		}
		.Control = &[0]
		.SetControllen(len())
	}
	if len() > 0 {
		.Iov = &[0]
		.SetIovlen(len())
	}
	if ,  = sendmsg(, &, );  != nil {
		return 0, 
	}
	if len() > 0 &&  {
		 = 0
	}
	return , nil
}

// BindToDevice binds the socket associated with fd to device.
func ( int,  string) ( error) {
	return SetsockoptString(, SOL_SOCKET, SO_BINDTODEVICE, )
}

//sys	ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
//sys	ptracePtr(request int, pid int, addr uintptr, data unsafe.Pointer) (err error) = SYS_PTRACE

func ptracePeek( int,  int,  uintptr,  []byte) ( int,  error) {
	// The peek requests are machine-size oriented, so we wrap it
	// to retrieve arbitrary-length data.

	// The ptrace syscall differs from glibc's ptrace.
	// Peeks returns the word in *data, not as the return value.

	var  [SizeofPtr]byte

	// Leading edge. PEEKTEXT/PEEKDATA don't require aligned
	// access (PEEKUSER warns that it might), but if we don't
	// align our reads, we might straddle an unmapped page
	// boundary and not get the bytes leading up to the page
	// boundary.
	 := 0
	if %SizeofPtr != 0 {
		 = ptracePtr(, , -%SizeofPtr, unsafe.Pointer(&[0]))
		if  != nil {
			return 0, 
		}
		 += copy(, [%SizeofPtr:])
		 = [:]
	}

	// Remainder.
	for len() > 0 {
		// We use an internal buffer to guarantee alignment.
		// It's not documented if this is necessary, but we're paranoid.
		 = ptracePtr(, , +uintptr(), unsafe.Pointer(&[0]))
		if  != nil {
			return , 
		}
		 := copy(, [0:])
		 += 
		 = [:]
	}

	return , nil
}

func ( int,  uintptr,  []byte) ( int,  error) {
	return ptracePeek(PTRACE_PEEKTEXT, , , )
}

func ( int,  uintptr,  []byte) ( int,  error) {
	return ptracePeek(PTRACE_PEEKDATA, , , )
}

func ( int,  uintptr,  []byte) ( int,  error) {
	return ptracePeek(PTRACE_PEEKUSR, , , )
}

func ptracePoke( int,  int,  int,  uintptr,  []byte) ( int,  error) {
	// As for ptracePeek, we need to align our accesses to deal
	// with the possibility of straddling an invalid page.

	// Leading edge.
	 := 0
	if %SizeofPtr != 0 {
		var  [SizeofPtr]byte
		 = ptracePtr(, , -%SizeofPtr, unsafe.Pointer(&[0]))
		if  != nil {
			return 0, 
		}
		 += copy([%SizeofPtr:], )
		 := *((*uintptr)(unsafe.Pointer(&[0])))
		 = ptrace(, , -%SizeofPtr, )
		if  != nil {
			return 0, 
		}
		 = [:]
	}

	// Interior.
	for len() > SizeofPtr {
		 := *((*uintptr)(unsafe.Pointer(&[0])))
		 = ptrace(, , +uintptr(), )
		if  != nil {
			return , 
		}
		 += SizeofPtr
		 = [SizeofPtr:]
	}

	// Trailing edge.
	if len() > 0 {
		var  [SizeofPtr]byte
		 = ptracePtr(, , +uintptr(), unsafe.Pointer(&[0]))
		if  != nil {
			return , 
		}
		copy([0:], )
		 := *((*uintptr)(unsafe.Pointer(&[0])))
		 = ptrace(, , +uintptr(), )
		if  != nil {
			return , 
		}
		 += len()
	}

	return , nil
}

func ( int,  uintptr,  []byte) ( int,  error) {
	return ptracePoke(PTRACE_POKETEXT, PTRACE_PEEKTEXT, , , )
}

func ( int,  uintptr,  []byte) ( int,  error) {
	return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, , , )
}

func ( int,  uintptr,  []byte) ( int,  error) {
	return ptracePoke(PTRACE_POKEUSR, PTRACE_PEEKUSR, , , )
}

// elfNT_PRSTATUS is a copy of the debug/elf.NT_PRSTATUS constant so
// x/sys/unix doesn't need to depend on debug/elf and thus
// compress/zlib, debug/dwarf, and other packages.
const elfNT_PRSTATUS = 1

func ( int,  *PtraceRegs) ( error) {
	var  Iovec
	.Base = (*byte)(unsafe.Pointer())
	.SetLen(int(unsafe.Sizeof(*)))
	return ptracePtr(PTRACE_GETREGSET, , uintptr(elfNT_PRSTATUS), unsafe.Pointer(&))
}

func ( int,  *PtraceRegs) ( error) {
	var  Iovec
	.Base = (*byte)(unsafe.Pointer())
	.SetLen(int(unsafe.Sizeof(*)))
	return ptracePtr(PTRACE_SETREGSET, , uintptr(elfNT_PRSTATUS), unsafe.Pointer(&))
}

func ( int,  int) ( error) {
	return ptrace(PTRACE_SETOPTIONS, , 0, uintptr())
}

func ( int) ( uint,  error) {
	var  _C_long
	 = ptracePtr(PTRACE_GETEVENTMSG, , 0, unsafe.Pointer(&))
	 = uint()
	return
}

func ( int,  int) ( error) {
	return ptrace(PTRACE_CONT, , 0, uintptr())
}

func ( int,  int) ( error) {
	return ptrace(PTRACE_SYSCALL, , 0, uintptr())
}

func ( int) ( error) { return ptrace(PTRACE_SINGLESTEP, , 0, 0) }

func ( int) ( error) { return ptrace(PTRACE_INTERRUPT, , 0, 0) }

func ( int) ( error) { return ptrace(PTRACE_ATTACH, , 0, 0) }

func ( int) ( error) { return ptrace(PTRACE_SEIZE, , 0, 0) }

func ( int) ( error) { return ptrace(PTRACE_DETACH, , 0, 0) }

//sys	reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error)

func ( int) ( error) {
	return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, , "")
}

func direntIno( []byte) (uint64, bool) {
	return readInt(, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
}

func direntReclen( []byte) (uint64, bool) {
	return readInt(, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
}

func direntNamlen( []byte) (uint64, bool) {
	,  := direntReclen()
	if ! {
		return 0, false
	}
	return  - uint64(unsafe.Offsetof(Dirent{}.Name)), true
}

//sys	mount(source string, target string, fstype string, flags uintptr, data *byte) (err error)

func ( string,  string,  string,  uintptr,  string) ( error) {
	// Certain file systems get rather angry and EINVAL if you give
	// them an empty string of data, rather than NULL.
	if  == "" {
		return mount(, , , , nil)
	}
	,  := BytePtrFromString()
	if  != nil {
		return 
	}
	return mount(, , , , )
}

//sys	mountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr, size uintptr) (err error) = SYS_MOUNT_SETATTR

// MountSetattr is a wrapper for mount_setattr(2).
// https://man7.org/linux/man-pages/man2/mount_setattr.2.html
//
// Requires kernel >= 5.12.
func ( int,  string,  uint,  *MountAttr) error {
	return mountSetattr(, , , , unsafe.Sizeof(*))
}

func ( int,  int,  *int64,  int) ( int,  error) {
	if raceenabled {
		raceReleaseMerge(unsafe.Pointer(&ioSync))
	}
	return sendfile(, , , )
}

// Sendto
// Recvfrom
// Socketpair

/*
 * Direct access
 */
//sys	Acct(path string) (err error)
//sys	AddKey(keyType string, description string, payload []byte, ringid int) (id int, err error)
//sys	Adjtimex(buf *Timex) (state int, err error)
//sysnb	Capget(hdr *CapUserHeader, data *CapUserData) (err error)
//sysnb	Capset(hdr *CapUserHeader, data *CapUserData) (err error)
//sys	Chdir(path string) (err error)
//sys	Chroot(path string) (err error)
//sys	ClockAdjtime(clockid int32, buf *Timex) (state int, err error)
//sys	ClockGetres(clockid int32, res *Timespec) (err error)
//sys	ClockGettime(clockid int32, time *Timespec) (err error)
//sys	ClockNanosleep(clockid int32, flags int, request *Timespec, remain *Timespec) (err error)
//sys	Close(fd int) (err error)
//sys	CloseRange(first uint, last uint, flags uint) (err error)
//sys	CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error)
//sys	DeleteModule(name string, flags int) (err error)
//sys	Dup(oldfd int) (fd int, err error)

func (,  int) error {
	return Dup3(, , 0)
}

//sys	Dup3(oldfd int, newfd int, flags int) (err error)
//sysnb	EpollCreate1(flag int) (fd int, err error)
//sysnb	EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error)
//sys	Eventfd(initval uint, flags int) (fd int, err error) = SYS_EVENTFD2
//sys	Exit(code int) = SYS_EXIT_GROUP
//sys	Fallocate(fd int, mode uint32, off int64, len int64) (err error)
//sys	Fchdir(fd int) (err error)
//sys	Fchmod(fd int, mode uint32) (err error)
//sys	Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
//sys	Fdatasync(fd int) (err error)
//sys	Fgetxattr(fd int, attr string, dest []byte) (sz int, err error)
//sys	FinitModule(fd int, params string, flags int) (err error)
//sys	Flistxattr(fd int, dest []byte) (sz int, err error)
//sys	Flock(fd int, how int) (err error)
//sys	Fremovexattr(fd int, attr string) (err error)
//sys	Fsetxattr(fd int, attr string, dest []byte, flags int) (err error)
//sys	Fsync(fd int) (err error)
//sys	Fsmount(fd int, flags int, mountAttrs int) (fsfd int, err error)
//sys	Fsopen(fsName string, flags int) (fd int, err error)
//sys	Fspick(dirfd int, pathName string, flags int) (fd int, err error)
//sys	Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64
//sysnb	Getpgid(pid int) (pgid int, err error)

func () ( int) {
	, _ = Getpgid(0)
	return
}

//sysnb	Getpid() (pid int)
//sysnb	Getppid() (ppid int)
//sys	Getpriority(which int, who int) (prio int, err error)
//sys	Getrandom(buf []byte, flags int) (n int, err error)
//sysnb	Getrusage(who int, rusage *Rusage) (err error)
//sysnb	Getsid(pid int) (sid int, err error)
//sysnb	Gettid() (tid int)
//sys	Getxattr(path string, attr string, dest []byte) (sz int, err error)
//sys	InitModule(moduleImage []byte, params string) (err error)
//sys	InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error)
//sysnb	InotifyInit1(flags int) (fd int, err error)
//sysnb	InotifyRmWatch(fd int, watchdesc uint32) (success int, err error)
//sysnb	Kill(pid int, sig syscall.Signal) (err error)
//sys	Klogctl(typ int, buf []byte) (n int, err error) = SYS_SYSLOG
//sys	Lgetxattr(path string, attr string, dest []byte) (sz int, err error)
//sys	Listxattr(path string, dest []byte) (sz int, err error)
//sys	Llistxattr(path string, dest []byte) (sz int, err error)
//sys	Lremovexattr(path string, attr string) (err error)
//sys	Lsetxattr(path string, attr string, data []byte, flags int) (err error)
//sys	MemfdCreate(name string, flags int) (fd int, 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	MoveMount(fromDirfd int, fromPathName string, toDirfd int, toPathName string, flags int) (err error)
//sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
//sys	OpenTree(dfd int, fileName string, flags uint) (r int, err error)
//sys	PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error)
//sys	PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
//sys	Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error)
//sys	pselect6(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *sigset_argpack) (n int, err error)
//sys	read(fd int, p []byte) (n int, err error)
//sys	Removexattr(path string, attr string) (err error)
//sys	Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error)
//sys	RequestKey(keyType string, description string, callback string, destRingid int) (id int, err error)
//sys	Setdomainname(p []byte) (err error)
//sys	Sethostname(p []byte) (err error)
//sysnb	Setpgid(pid int, pgid int) (err error)
//sysnb	Setsid() (pid int, err error)
//sysnb	Settimeofday(tv *Timeval) (err error)
//sys	Setns(fd int, nstype int) (err error)

//go:linkname syscall_prlimit syscall.prlimit
func syscall_prlimit(,  int, ,  *syscall.Rlimit) error

func (,  int, ,  *Rlimit) error {
	// Just call the syscall version, because as of Go 1.21
	// it will affect starting a new process.
	return syscall_prlimit(, , (*syscall.Rlimit)(), (*syscall.Rlimit)())
}

// PrctlRetInt performs a prctl operation specified by option and further
// optional arguments arg2 through arg5 depending on option. It returns a
// non-negative integer that is returned by the prctl syscall.
func ( int,  uintptr,  uintptr,  uintptr,  uintptr) (int, error) {
	, ,  := Syscall6(SYS_PRCTL, uintptr(), uintptr(), uintptr(), uintptr(), uintptr(), 0)
	if  != 0 {
		return 0, 
	}
	return int(), nil
}

func ( int) ( error) {
	return syscall.Setuid()
}

func ( int) ( error) {
	return syscall.Setgid()
}

func (,  int) ( error) {
	return syscall.Setreuid(, )
}

func (,  int) ( error) {
	return syscall.Setregid(, )
}

func (, ,  int) ( error) {
	return syscall.Setresuid(, , )
}

func (, ,  int) ( error) {
	return syscall.Setresgid(, , )
}

// SetfsgidRetGid sets fsgid for current thread and returns previous fsgid set.
// setfsgid(2) will return a non-nil error only if its caller lacks CAP_SETUID capability.
// If the call fails due to other reasons, current fsgid will be returned.
func ( int) (int, error) {
	return setfsgid()
}

// SetfsuidRetUid sets fsuid for current thread and returns previous fsuid set.
// setfsgid(2) will return a non-nil error only if its caller lacks CAP_SETUID capability
// If the call fails due to other reasons, current fsuid will be returned.
func ( int) (int, error) {
	return setfsuid()
}

func ( int) error {
	,  := setfsgid()
	return 
}

func ( int) error {
	,  := setfsuid()
	return 
}

func ( int,  *Sigset_t,  int) ( int,  error) {
	return signalfd(, , _C__NSIG/8, )
}

//sys	Setpriority(which int, who int, prio int) (err error)
//sys	Setxattr(path string, attr string, data []byte, flags int) (err error)
//sys	signalfd(fd int, sigmask *Sigset_t, maskSize uintptr, flags int) (newfd int, err error) = SYS_SIGNALFD4
//sys	Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error)
//sys	Sync()
//sys	Syncfs(fd int) (err error)
//sysnb	Sysinfo(info *Sysinfo_t) (err error)
//sys	Tee(rfd int, wfd int, len int, flags int) (n int64, err error)
//sysnb	TimerfdCreate(clockid int, flags int) (fd int, err error)
//sysnb	TimerfdGettime(fd int, currValue *ItimerSpec) (err error)
//sysnb	TimerfdSettime(fd int, flags int, newValue *ItimerSpec, oldValue *ItimerSpec) (err error)
//sysnb	Tgkill(tgid int, tid int, sig syscall.Signal) (err error)
//sysnb	Times(tms *Tms) (ticks uintptr, err error)
//sysnb	Umask(mask int) (oldmask int)
//sysnb	Uname(buf *Utsname) (err error)
//sys	Unmount(target string, flags int) (err error) = SYS_UMOUNT2
//sys	Unshare(flags int) (err error)
//sys	write(fd int, p []byte) (n int, err error)
//sys	exitThread(code int) (err error) = SYS_EXIT
//sys	readv(fd int, iovs []Iovec) (n int, err error) = SYS_READV
//sys	writev(fd int, iovs []Iovec) (n int, err error) = SYS_WRITEV
//sys	preadv(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) = SYS_PREADV
//sys	pwritev(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) = SYS_PWRITEV
//sys	preadv2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PREADV2
//sys	pwritev2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PWRITEV2

// minIovec is the size of the small initial allocation used by
// Readv, Writev, etc.
//
// This small allocation gets stack allocated, which lets the
// common use case of len(iovs) <= minIovs avoid more expensive
// heap allocations.
const minIovec = 8

// appendBytes converts bs to Iovecs and appends them to vecs.
func appendBytes( []Iovec,  [][]byte) []Iovec {
	for ,  := range  {
		var  Iovec
		.SetLen(len())
		if len() > 0 {
			.Base = &[0]
		} else {
			.Base = (*byte)(unsafe.Pointer(&_zero))
		}
		 = append(, )
	}
	return 
}

// offs2lohi splits offs into its low and high order bits.
func offs2lohi( int64) (,  uintptr) {
	const  = SizeofLong * 8
	return uintptr(), uintptr(uint64() >> ( - 1) >> 1) // two shifts to avoid false positive in vet
}

func ( int,  [][]byte) ( int,  error) {
	 := make([]Iovec, 0, minIovec)
	 = appendBytes(, )
	,  = readv(, )
	readvRacedetect(, , )
	return , 
}

func ( int,  [][]byte,  int64) ( int,  error) {
	 := make([]Iovec, 0, minIovec)
	 = appendBytes(, )
	,  := offs2lohi()
	,  = preadv(, , , )
	readvRacedetect(, , )
	return , 
}

func ( int,  [][]byte,  int64,  int) ( int,  error) {
	 := make([]Iovec, 0, minIovec)
	 = appendBytes(, )
	,  := offs2lohi()
	,  = preadv2(, , , , )
	readvRacedetect(, , )
	return , 
}

func readvRacedetect( []Iovec,  int,  error) {
	if !raceenabled {
		return
	}
	for  := 0;  > 0 &&  < len(); ++ {
		 := int([].Len)
		if  >  {
			 = 
		}
		 -= 
		if  > 0 {
			raceWriteRange(unsafe.Pointer([].Base), )
		}
	}
	if  == nil {
		raceAcquire(unsafe.Pointer(&ioSync))
	}
}

func ( int,  [][]byte) ( int,  error) {
	 := make([]Iovec, 0, minIovec)
	 = appendBytes(, )
	if raceenabled {
		raceReleaseMerge(unsafe.Pointer(&ioSync))
	}
	,  = writev(, )
	writevRacedetect(, )
	return , 
}

func ( int,  [][]byte,  int64) ( int,  error) {
	 := make([]Iovec, 0, minIovec)
	 = appendBytes(, )
	if raceenabled {
		raceReleaseMerge(unsafe.Pointer(&ioSync))
	}
	,  := offs2lohi()
	,  = pwritev(, , , )
	writevRacedetect(, )
	return , 
}

func ( int,  [][]byte,  int64,  int) ( int,  error) {
	 := make([]Iovec, 0, minIovec)
	 = appendBytes(, )
	if raceenabled {
		raceReleaseMerge(unsafe.Pointer(&ioSync))
	}
	,  := offs2lohi()
	,  = pwritev2(, , , , )
	writevRacedetect(, )
	return , 
}

func writevRacedetect( []Iovec,  int) {
	if !raceenabled {
		return
	}
	for  := 0;  > 0 &&  < len(); ++ {
		 := int([].Len)
		if  >  {
			 = 
		}
		 -= 
		if  > 0 {
			raceReadRange(unsafe.Pointer([].Base), )
		}
	}
}

// mmap varies by architecture; see syscall_linux_*.go.
//sys	munmap(addr uintptr, length uintptr) (err error)
//sys	mremap(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error)
//sys	Madvise(b []byte, advice int) (err error)
//sys	Mprotect(b []byte, prot int) (err error)
//sys	Mlock(b []byte) (err error)
//sys	Mlockall(flags int) (err error)
//sys	Msync(b []byte, flags int) (err error)
//sys	Munlock(b []byte) (err error)
//sys	Munlockall() (err error)

const (
	mremapFixed     = MREMAP_FIXED
	mremapDontunmap = MREMAP_DONTUNMAP
	mremapMaymove   = MREMAP_MAYMOVE
)

// Vmsplice splices user pages from a slice of Iovecs into a pipe specified by fd,
// using the specified flags.
func ( int,  []Iovec,  int) (int, error) {
	var  unsafe.Pointer
	if len() > 0 {
		 = unsafe.Pointer(&[0])
	}

	, ,  := Syscall6(SYS_VMSPLICE, uintptr(), uintptr(), uintptr(len()), uintptr(), 0, 0)
	if  != 0 {
		return 0, syscall.Errno()
	}

	return int(), nil
}

func isGroupMember( int) bool {
	,  := Getgroups()
	if  != nil {
		return false
	}

	for ,  := range  {
		if  ==  {
			return true
		}
	}
	return false
}

func isCapDacOverrideSet() bool {
	 := CapUserHeader{Version: LINUX_CAPABILITY_VERSION_3}
	 := [2]CapUserData{}
	 := Capget(&, &[0])

	return  == nil && [0].Effective&(1<<CAP_DAC_OVERRIDE) != 0
}

//sys	faccessat(dirfd int, path string, mode uint32) (err error)
//sys	Faccessat2(dirfd int, path string, mode uint32, flags int) (err error)

func ( int,  string,  uint32,  int) ( error) {
	if  == 0 {
		return faccessat(, , )
	}

	if  := Faccessat2(, , , );  != ENOSYS &&  != EPERM {
		return 
	}

	// The Linux kernel faccessat system call does not take any flags.
	// The glibc faccessat implements the flags itself; see
	// https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/faccessat.c;hb=HEAD
	// Because people naturally expect syscall.Faccessat to act
	// like C faccessat, we do the same.

	if  & ^(AT_SYMLINK_NOFOLLOW|AT_EACCESS) != 0 {
		return EINVAL
	}

	var  Stat_t
	if  := Fstatat(, , &, &AT_SYMLINK_NOFOLLOW);  != nil {
		return 
	}

	 &= 7
	if  == 0 {
		return nil
	}

	var  int
	if &AT_EACCESS != 0 {
		 = Geteuid()
		if  != 0 && isCapDacOverrideSet() {
			// If CAP_DAC_OVERRIDE is set, file access check is
			// done by the kernel in the same way as for root
			// (see generic_permission() in the Linux sources).
			 = 0
		}
	} else {
		 = Getuid()
	}

	if  == 0 {
		if &1 == 0 {
			// Root can read and write any file.
			return nil
		}
		if .Mode&0111 != 0 {
			// Root can execute any file that anybody can execute.
			return nil
		}
		return EACCES
	}

	var  uint32
	if uint32() == .Uid {
		 = (.Mode >> 6) & 7
	} else {
		var  int
		if &AT_EACCESS != 0 {
			 = Getegid()
		} else {
			 = Getgid()
		}

		if uint32() == .Gid || isGroupMember(int(.Gid)) {
			 = (.Mode >> 3) & 7
		} else {
			 = .Mode & 7
		}
	}

	if & ==  {
		return nil
	}

	return EACCES
}

//sys	nameToHandleAt(dirFD int, pathname string, fh *fileHandle, mountID *_C_int, flags int) (err error) = SYS_NAME_TO_HANDLE_AT
//sys	openByHandleAt(mountFD int, fh *fileHandle, flags int) (fd int, err error) = SYS_OPEN_BY_HANDLE_AT

// fileHandle is the argument to nameToHandleAt and openByHandleAt. We
// originally tried to generate it via unix/linux/types.go with "type
// fileHandle C.struct_file_handle" but that generated empty structs
// for mips64 and mips64le. Instead, hard code it for now (it's the
// same everywhere else) until the mips64 generator issue is fixed.
type fileHandle struct {
	Bytes uint32
	Type  int32
}

// FileHandle represents the C struct file_handle used by
// name_to_handle_at (see NameToHandleAt) and open_by_handle_at (see
// OpenByHandleAt).
type FileHandle struct {
	*fileHandle
}

// NewFileHandle constructs a FileHandle.
func ( int32,  []byte) FileHandle {
	const  = unsafe.Sizeof(fileHandle{})
	 := make([]byte, +uintptr(len()))
	copy([:], )
	 := (*fileHandle)(unsafe.Pointer(&[0]))
	.Type = 
	.Bytes = uint32(len())
	return FileHandle{}
}

func ( *FileHandle) () int   { return int(.fileHandle.Bytes) }
func ( *FileHandle) () int32 { return .fileHandle.Type }
func ( *FileHandle) () []byte {
	 := .Size()
	if  == 0 {
		return nil
	}
	return unsafe.Slice((*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&.fileHandle.Type))+4)), )
}

// NameToHandleAt wraps the name_to_handle_at system call; it obtains
// a handle for a path name.
func ( int,  string,  int) ( FileHandle,  int,  error) {
	var  _C_int
	// Try first with a small buffer, assuming the handle will
	// only be 32 bytes.
	 := uint32(32 + unsafe.Sizeof(fileHandle{}))
	 := false
	for {
		 := make([]byte, )
		 := (*fileHandle)(unsafe.Pointer(&[0]))
		.Bytes =  - uint32(unsafe.Sizeof(fileHandle{}))
		 = nameToHandleAt(, , , &, )
		if  == EOVERFLOW {
			if  {
				// We shouldn't need to resize more than once
				return
			}
			 = true
			 = .Bytes + uint32(unsafe.Sizeof(fileHandle{}))
			continue
		}
		if  != nil {
			return
		}
		return FileHandle{}, int(), nil
	}
}

// OpenByHandleAt wraps the open_by_handle_at system call; it opens a
// file via a handle as previously returned by NameToHandleAt.
func ( int,  FileHandle,  int) ( int,  error) {
	return openByHandleAt(, .fileHandle, )
}

// Klogset wraps the sys_syslog system call; it sets console_loglevel to
// the value specified by arg and passes a dummy pointer to bufp.
func ( int,  int) ( error) {
	var  unsafe.Pointer
	, ,  := Syscall(SYS_SYSLOG, uintptr(), uintptr(), uintptr())
	if  != 0 {
		return errnoErr()
	}
	return nil
}

// RemoteIovec is Iovec with the pointer replaced with an integer.
// It is used for ProcessVMReadv and ProcessVMWritev, where the pointer
// refers to a location in a different process' address space, which
// would confuse the Go garbage collector.
type RemoteIovec struct {
	Base uintptr
	Len  int
}

//sys	ProcessVMReadv(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_READV
//sys	ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_WRITEV

//sys	PidfdOpen(pid int, flags int) (fd int, err error) = SYS_PIDFD_OPEN
//sys	PidfdGetfd(pidfd int, targetfd int, flags int) (fd int, err error) = SYS_PIDFD_GETFD
//sys	PidfdSendSignal(pidfd int, sig Signal, info *Siginfo, flags int) (err error) = SYS_PIDFD_SEND_SIGNAL

//sys	shmat(id int, addr uintptr, flag int) (ret uintptr, err error)
//sys	shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error)
//sys	shmdt(addr uintptr) (err error)
//sys	shmget(key int, size int, flag int) (id int, err error)

//sys	getitimer(which int, currValue *Itimerval) (err error)
//sys	setitimer(which int, newValue *Itimerval, oldValue *Itimerval) (err error)

// MakeItimerval creates an Itimerval from interval and value durations.
func (,  time.Duration) Itimerval {
	return Itimerval{
		Interval: NsecToTimeval(.Nanoseconds()),
		Value:    NsecToTimeval(.Nanoseconds()),
	}
}

// A value which may be passed to the which parameter for Getitimer and
// Setitimer.
type ItimerWhich int

// Possible which values for Getitimer and Setitimer.
const (
	ItimerReal    ItimerWhich = ITIMER_REAL
	ItimerVirtual ItimerWhich = ITIMER_VIRTUAL
	ItimerProf    ItimerWhich = ITIMER_PROF
)

// Getitimer wraps getitimer(2) to return the current value of the timer
// specified by which.
func ( ItimerWhich) (Itimerval, error) {
	var  Itimerval
	if  := getitimer(int(), &);  != nil {
		return Itimerval{}, 
	}

	return , nil
}

// Setitimer wraps setitimer(2) to arm or disarm the timer specified by which.
// It returns the previous value of the timer.
//
// If the Itimerval argument is the zero value, the timer will be disarmed.
func ( ItimerWhich,  Itimerval) (Itimerval, error) {
	var  Itimerval
	if  := setitimer(int(), &, &);  != nil {
		return Itimerval{}, 
	}

	return , nil
}

//sysnb	rtSigprocmask(how int, set *Sigset_t, oldset *Sigset_t, sigsetsize uintptr) (err error) = SYS_RT_SIGPROCMASK

func ( int, ,  *Sigset_t) error {
	if  != nil {
		// Explicitly clear in case Sigset_t is larger than _C__NSIG.
		* = Sigset_t{}
	}
	return rtSigprocmask(, , , _C__NSIG/8)
}

//sysnb	getresuid(ruid *_C_int, euid *_C_int, suid *_C_int)
//sysnb	getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int)

func () (, ,  int) {
	var , ,  _C_int
	getresuid(&, &, &)
	return int(), int(), int()
}

func () (, ,  int) {
	var , ,  _C_int
	getresgid(&, &, &)
	return int(), int(), int()
}

// Pselect is a wrapper around the Linux pselect6 system call.
// This version does not modify the timeout argument.
func ( int,  *FdSet,  *FdSet,  *FdSet,  *Timespec,  *Sigset_t) ( int,  error) {
	// Per https://man7.org/linux/man-pages/man2/select.2.html#NOTES,
	// The Linux pselect6() system call modifies its timeout argument.
	// [Not modifying the argument] is the behavior required by POSIX.1-2001.
	var  *Timespec
	if  != nil {
		 = new(Timespec)
		* = *
	}

	// The final argument of the pselect6() system call is not a
	// sigset_t * pointer, but is instead a structure
	var  *sigset_argpack
	if  != nil {
		 := 32 << (^uintptr(0) >> 63) // see math.intSize

		// A sigset stores one bit per signal,
		// offset by 1 (because signal 0 does not exist).
		// So the number of words needed is ⌈__C_NSIG - 1 / wordBits⌉.
		 := (_C__NSIG - 1 +  - 1) / ()

		 := uintptr( * ( / 8))
		 = &sigset_argpack{
			ss:    ,
			ssLen: ,
		}
	}

	return pselect6(, , , , , )
}

//sys	schedSetattr(pid int, attr *SchedAttr, flags uint) (err error)
//sys	schedGetattr(pid int, attr *SchedAttr, size uint, flags uint) (err error)

// SchedSetAttr is a wrapper for sched_setattr(2) syscall.
// https://man7.org/linux/man-pages/man2/sched_setattr.2.html
func ( int,  *SchedAttr,  uint) error {
	if  == nil {
		return EINVAL
	}
	.Size = SizeofSchedAttr
	return schedSetattr(, , )
}

// SchedGetAttr is a wrapper for sched_getattr(2) syscall.
// https://man7.org/linux/man-pages/man2/sched_getattr.2.html
func ( int,  uint) (*SchedAttr, error) {
	 := &SchedAttr{}
	if  := schedGetattr(, , SizeofSchedAttr, );  != nil {
		return nil, 
	}
	return , nil
}