1065 lines · 26.6 KB · Go
RawDownload
// 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 syscall import "unsafe" /* * Wrapped */ func Access(path string, mode uint32) (err error) {	return Faccessat(_AT_FDCWD, path, mode, 0)} func Chmod(path string, mode uint32) (err error) {	return Fchmodat(_AT_FDCWD, path, mode, 0)} func Chown(path string, uid int, gid int) (err error) {	return Fchownat(_AT_FDCWD, path, uid, gid, 0)} func Creat(path string, mode uint32) (fd int, err error) {	return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode)} //sys	linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) func Link(oldpath string, newpath string) (err error) {	return linkat(_AT_FDCWD, oldpath, _AT_FDCWD, newpath, 0)} func Mkdir(path string, mode uint32) (err error) {	return Mkdirat(_AT_FDCWD, path, mode)} func Mknod(path string, mode uint32, dev int) (err error) {	return Mknodat(_AT_FDCWD, path, mode, dev)} func Open(path string, mode int, perm uint32) (fd int, err error) {	return openat(_AT_FDCWD, path, mode|O_LARGEFILE, perm)} //sys	openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {	return openat(dirfd, path, flags|O_LARGEFILE, mode)} //sys	readlinkat(dirfd int, path string, buf []byte) (n int, err error) func Readlink(path string, buf []byte) (n int, err error) {	return readlinkat(_AT_FDCWD, path, buf)} func Rename(oldpath string, newpath string) (err error) {	return Renameat(_AT_FDCWD, oldpath, _AT_FDCWD, newpath)} func Rmdir(path string) error {	return unlinkat(_AT_FDCWD, path, _AT_REMOVEDIR)} //sys	symlinkat(oldpath string, newdirfd int, newpath string) (err error) func Symlink(oldpath string, newpath string) (err error) {	return symlinkat(oldpath, _AT_FDCWD, newpath)} func Unlink(path string) error {	return unlinkat(_AT_FDCWD, path, 0)} //sys	unlinkat(dirfd int, path string, flags int) (err error) func Unlinkat(dirfd int, path string) error {	return unlinkat(dirfd, path, 0)} //sys	utimes(path string, times *[2]Timeval) (err error) func Utimes(path string, tv []Timeval) (err 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) (err error) func UtimesNano(path string, ts []Timespec) (err error) {	if len(ts) != 2 {		return EINVAL	}	err = utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])))	if err != ENOSYS {		return err	}	// If the utimensat syscall isn't available (utimensat was added to Linux	// in 2.6.22, Released, 8 July 2007) then fall back to utimes	var tv [2]Timeval	for i := 0; i < 2; i++ {		tv[i].Sec = ts[i].Sec		tv[i].Usec = ts[i].Nsec / 1000	}	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))} //sys	futimesat(dirfd int, path *byte, times *[2]Timeval) (err error) func Futimesat(dirfd int, path string, tv []Timeval) (err error) {	if len(tv) != 2 {		return EINVAL	}	pathp, err := BytePtrFromString(path)	if err != nil {		return err	}	err = futimesat(dirfd, pathp, (*[2]Timeval)(unsafe.Pointer(&tv[0])))	use(unsafe.Pointer(pathp))	return err} func Futimes(fd int, tv []Timeval) (err error) {	// Believe it or not, this is the best we can do on Linux	// (and is what glibc does).	return Utimes("/proc/self/fd/"+itoa(fd), tv)} const ImplementsGetwd = true //sys	Getcwd(buf []byte) (n int, err error) func Getwd() (wd string, err error) {	var buf [PathMax]byte	n, err := Getcwd(buf[0:])	if err != nil {		return "", err	}	// Getcwd returns the number of bytes written to buf, including the NUL.	if n < 1 || n > len(buf) || buf[n-1] != 0 {		return "", EINVAL	}	return string(buf[0 : n-1]), nil} 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 1<<16 on Linux.	if n < 0 || n > 1<<20 {		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])} 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 (w WaitStatus) Exited() bool { return w&mask == exited } func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited } func (w WaitStatus) Stopped() bool { return w&0xFF == stopped } func (w WaitStatus) Continued() bool { return w == 0xFFFF } func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 } func (w WaitStatus) ExitStatus() int {	if !w.Exited() {		return -1	}	return int(w>>shift) & 0xFF} func (w WaitStatus) Signal() Signal {	if !w.Signaled() {		return -1	}	return Signal(w & mask)} func (w WaitStatus) StopSignal() Signal {	if !w.Stopped() {		return -1	}	return Signal(w>>shift) & 0xFF} func (w WaitStatus) TrapCause() int {	if w.StopSignal() != SIGTRAP {		return -1	}	return int(w>>shift) >> 8} //sys	wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {	var status _C_int	wpid, err = wait4(pid, &status, options, rusage)	if wstatus != nil {		*wstatus = WaitStatus(status)	}	return} func Mkfifo(path string, mode uint32) (err error) {	return Mknod(path, mode|S_IFIFO, 0)} 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 *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	for i := 0; i < n; i++ {		sa.raw.Path[i] = int8(name[i])	}	// length is family (uint16), name, NUL.	sl := _Socklen(2)	if n > 0 {		sl += _Socklen(n) + 1	}	if sa.raw.Path[0] == '@' {		sa.raw.Path[0] = 0		// Don't count trailing NUL for abstract address.		sl--	} 	return unsafe.Pointer(&sa.raw), sl, nil} type SockaddrLinklayer struct {	Protocol uint16	Ifindex  int	Hatype   uint16	Pkttype  uint8	Halen    uint8	Addr     [8]byte	raw      RawSockaddrLinklayer} func (sa *SockaddrLinklayer) sockaddr() (unsafe.Pointer, _Socklen, error) {	if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff {		return nil, 0, EINVAL	}	sa.raw.Family = AF_PACKET	sa.raw.Protocol = sa.Protocol	sa.raw.Ifindex = int32(sa.Ifindex)	sa.raw.Hatype = sa.Hatype	sa.raw.Pkttype = sa.Pkttype	sa.raw.Halen = sa.Halen	for i := 0; i < len(sa.Addr); i++ {		sa.raw.Addr[i] = sa.Addr[i]	}	return unsafe.Pointer(&sa.raw), SizeofSockaddrLinklayer, nil} type SockaddrNetlink struct {	Family uint16	Pad    uint16	Pid    uint32	Groups uint32	raw    RawSockaddrNetlink} func (sa *SockaddrNetlink) sockaddr() (unsafe.Pointer, _Socklen, error) {	sa.raw.Family = AF_NETLINK	sa.raw.Pad = sa.Pad	sa.raw.Pid = sa.Pid	sa.raw.Groups = sa.Groups	return unsafe.Pointer(&sa.raw), SizeofSockaddrNetlink, nil} func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {	switch rsa.Addr.Family {	case AF_NETLINK:		pp := (*RawSockaddrNetlink)(unsafe.Pointer(rsa))		sa := new(SockaddrNetlink)		sa.Family = pp.Family		sa.Pad = pp.Pad		sa.Pid = pp.Pid		sa.Groups = pp.Groups		return sa, nil 	case AF_PACKET:		pp := (*RawSockaddrLinklayer)(unsafe.Pointer(rsa))		sa := new(SockaddrLinklayer)		sa.Protocol = pp.Protocol		sa.Ifindex = int(pp.Ifindex)		sa.Hatype = pp.Hatype		sa.Pkttype = pp.Pkttype		sa.Halen = pp.Halen		for i := 0; i < len(sa.Addr); i++ {			sa.Addr[i] = pp.Addr[i]		}		return sa, nil 	case AF_UNIX:		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))		sa := new(SockaddrUnix)		if pp.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.			pp.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.		n := 0		for n < len(pp.Path) && pp.Path[n] != 0 {			n++		}		bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]		sa.Name = string(bytes)		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])		sa.ZoneId = pp.Scope_id		for i := 0; i < len(sa.Addr); i++ {			sa.Addr[i] = pp.Addr[i]		}		return sa, nil	}	return nil, EAFNOSUPPORT} 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 Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) {	var rsa RawSockaddrAny	var len _Socklen = SizeofSockaddrAny	nfd, err = accept4(fd, &rsa, &len, flags)	if err != nil {		return	}	if len > SizeofSockaddrAny {		panic("RawSockaddrAny too small")	}	sa, err = anyToSockaddr(&rsa)	if err != nil {		Close(nfd)		nfd = 0	}	return} 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)} func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) {	vallen := _Socklen(4)	err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)	return value, err} func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {	var value IPMreq	vallen := _Socklen(SizeofIPMreq)	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)	return &value, err} func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {	var value IPMreqn	vallen := _Socklen(SizeofIPMreqn)	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)	return &value, err} func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {	var value IPv6Mreq	vallen := _Socklen(SizeofIPv6Mreq)	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)

Lines 1–500 of 1065.