1a2f01efa6
Update the Go library to the 1.10beta1 release. Requires a few changes to the compiler for modifications to the map runtime code, and to handle some nowritebarrier cases in the runtime. Reviewed-on: https://go-review.googlesource.com/86455 gotools/: * Makefile.am (go_cmd_vet_files): New variable. (go_cmd_buildid_files, go_cmd_test2json_files): New variables. (s-zdefaultcc): Change from constants to functions. (noinst_PROGRAMS): Add vet, buildid, and test2json. (cgo$(EXEEXT)): Link against $(LIBGOTOOL). (vet$(EXEEXT)): New target. (buildid$(EXEEXT)): New target. (test2json$(EXEEXT)): New target. (install-exec-local): Install all $(noinst_PROGRAMS). (uninstall-local): Uninstasll all $(noinst_PROGRAMS). (check-go-tool): Depend on $(noinst_PROGRAMS). Copy down objabi.go. (check-runtime): Depend on $(noinst_PROGRAMS). (check-cgo-test, check-carchive-test): Likewise. (check-vet): New target. (check): Depend on check-vet. Look at cmd_vet-testlog. (.PHONY): Add check-vet. * Makefile.in: Rebuild. From-SVN: r256365
344 lines
9.8 KiB
Go
344 lines
9.8 KiB
Go
// 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.
|
|
|
|
package net
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"sync"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
// UnixAddr represents the address of a Unix domain socket end point.
|
|
type UnixAddr struct {
|
|
Name string
|
|
Net string
|
|
}
|
|
|
|
// Network returns the address's network name, "unix", "unixgram" or
|
|
// "unixpacket".
|
|
func (a *UnixAddr) Network() string {
|
|
return a.Net
|
|
}
|
|
|
|
func (a *UnixAddr) String() string {
|
|
if a == nil {
|
|
return "<nil>"
|
|
}
|
|
return a.Name
|
|
}
|
|
|
|
func (a *UnixAddr) isWildcard() bool {
|
|
return a == nil || a.Name == ""
|
|
}
|
|
|
|
func (a *UnixAddr) opAddr() Addr {
|
|
if a == nil {
|
|
return nil
|
|
}
|
|
return a
|
|
}
|
|
|
|
// ResolveUnixAddr returns an address of Unix domain socket end point.
|
|
//
|
|
// The network must be a Unix network name.
|
|
//
|
|
// See func Dial for a description of the network and address
|
|
// parameters.
|
|
func ResolveUnixAddr(network, address string) (*UnixAddr, error) {
|
|
switch network {
|
|
case "unix", "unixgram", "unixpacket":
|
|
return &UnixAddr{Name: address, Net: network}, nil
|
|
default:
|
|
return nil, UnknownNetworkError(network)
|
|
}
|
|
}
|
|
|
|
// UnixConn is an implementation of the Conn interface for connections
|
|
// to Unix domain sockets.
|
|
type UnixConn struct {
|
|
conn
|
|
}
|
|
|
|
// SyscallConn returns a raw network connection.
|
|
// This implements the syscall.Conn interface.
|
|
func (c *UnixConn) SyscallConn() (syscall.RawConn, error) {
|
|
if !c.ok() {
|
|
return nil, syscall.EINVAL
|
|
}
|
|
return newRawConn(c.fd)
|
|
}
|
|
|
|
// CloseRead shuts down the reading side of the Unix domain connection.
|
|
// Most callers should just use Close.
|
|
func (c *UnixConn) CloseRead() error {
|
|
if !c.ok() {
|
|
return syscall.EINVAL
|
|
}
|
|
if err := c.fd.closeRead(); err != nil {
|
|
return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// CloseWrite shuts down the writing side of the Unix domain connection.
|
|
// Most callers should just use Close.
|
|
func (c *UnixConn) CloseWrite() error {
|
|
if !c.ok() {
|
|
return syscall.EINVAL
|
|
}
|
|
if err := c.fd.closeWrite(); err != nil {
|
|
return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ReadFromUnix acts like ReadFrom but returns a UnixAddr.
|
|
func (c *UnixConn) ReadFromUnix(b []byte) (int, *UnixAddr, error) {
|
|
if !c.ok() {
|
|
return 0, nil, syscall.EINVAL
|
|
}
|
|
n, addr, err := c.readFrom(b)
|
|
if err != nil {
|
|
err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
|
|
}
|
|
return n, addr, err
|
|
}
|
|
|
|
// ReadFrom implements the PacketConn ReadFrom method.
|
|
func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
|
|
if !c.ok() {
|
|
return 0, nil, syscall.EINVAL
|
|
}
|
|
n, addr, err := c.readFrom(b)
|
|
if err != nil {
|
|
err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
|
|
}
|
|
if addr == nil {
|
|
return n, nil, err
|
|
}
|
|
return n, addr, err
|
|
}
|
|
|
|
// ReadMsgUnix reads a message from c, copying the payload into b and
|
|
// the associated out-of-band data into oob. It returns the number of
|
|
// bytes copied into b, the number of bytes copied into oob, the flags
|
|
// that were set on the message and the source address of the message.
|
|
//
|
|
// Note that if len(b) == 0 and len(oob) > 0, this function will still
|
|
// read (and discard) 1 byte from the connection.
|
|
func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
|
|
if !c.ok() {
|
|
return 0, 0, 0, nil, syscall.EINVAL
|
|
}
|
|
n, oobn, flags, addr, err = c.readMsg(b, oob)
|
|
if err != nil {
|
|
err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
|
|
}
|
|
return
|
|
}
|
|
|
|
// WriteToUnix acts like WriteTo but takes a UnixAddr.
|
|
func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (int, error) {
|
|
if !c.ok() {
|
|
return 0, syscall.EINVAL
|
|
}
|
|
n, err := c.writeTo(b, addr)
|
|
if err != nil {
|
|
err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
|
|
}
|
|
return n, err
|
|
}
|
|
|
|
// WriteTo implements the PacketConn WriteTo method.
|
|
func (c *UnixConn) WriteTo(b []byte, addr Addr) (int, error) {
|
|
if !c.ok() {
|
|
return 0, syscall.EINVAL
|
|
}
|
|
a, ok := addr.(*UnixAddr)
|
|
if !ok {
|
|
return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
|
|
}
|
|
n, err := c.writeTo(b, a)
|
|
if err != nil {
|
|
err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: a.opAddr(), Err: err}
|
|
}
|
|
return n, err
|
|
}
|
|
|
|
// WriteMsgUnix writes a message to addr via c, copying the payload
|
|
// from b and the associated out-of-band data from oob. It returns the
|
|
// number of payload and out-of-band bytes written.
|
|
//
|
|
// Note that if len(b) == 0 and len(oob) > 0, this function will still
|
|
// write 1 byte to the connection.
|
|
func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
|
|
if !c.ok() {
|
|
return 0, 0, syscall.EINVAL
|
|
}
|
|
n, oobn, err = c.writeMsg(b, oob, addr)
|
|
if err != nil {
|
|
err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
|
|
}
|
|
return
|
|
}
|
|
|
|
func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{conn{fd}} }
|
|
|
|
// DialUnix acts like Dial for Unix networks.
|
|
//
|
|
// The network must be a Unix network name; see func Dial for details.
|
|
//
|
|
// If laddr is non-nil, it is used as the local address for the
|
|
// connection.
|
|
func DialUnix(network string, laddr, raddr *UnixAddr) (*UnixConn, error) {
|
|
switch network {
|
|
case "unix", "unixgram", "unixpacket":
|
|
default:
|
|
return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(network)}
|
|
}
|
|
c, err := dialUnix(context.Background(), network, laddr, raddr)
|
|
if err != nil {
|
|
return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
|
|
}
|
|
return c, nil
|
|
}
|
|
|
|
// UnixListener is a Unix domain socket listener. Clients should
|
|
// typically use variables of type Listener instead of assuming Unix
|
|
// domain sockets.
|
|
type UnixListener struct {
|
|
fd *netFD
|
|
path string
|
|
unlink bool
|
|
unlinkOnce sync.Once
|
|
}
|
|
|
|
func (ln *UnixListener) ok() bool { return ln != nil && ln.fd != nil }
|
|
|
|
// SyscallConn returns a raw network connection.
|
|
// This implements the syscall.Conn interface.
|
|
//
|
|
// The returned RawConn only supports calling Control. Read and
|
|
// Write return an error.
|
|
func (l *UnixListener) SyscallConn() (syscall.RawConn, error) {
|
|
if !l.ok() {
|
|
return nil, syscall.EINVAL
|
|
}
|
|
return newRawListener(l.fd)
|
|
}
|
|
|
|
// AcceptUnix accepts the next incoming call and returns the new
|
|
// connection.
|
|
func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
|
|
if !l.ok() {
|
|
return nil, syscall.EINVAL
|
|
}
|
|
c, err := l.accept()
|
|
if err != nil {
|
|
return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
|
|
}
|
|
return c, nil
|
|
}
|
|
|
|
// Accept implements the Accept method in the Listener interface.
|
|
// Returned connections will be of type *UnixConn.
|
|
func (l *UnixListener) Accept() (Conn, error) {
|
|
if !l.ok() {
|
|
return nil, syscall.EINVAL
|
|
}
|
|
c, err := l.accept()
|
|
if err != nil {
|
|
return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
|
|
}
|
|
return c, nil
|
|
}
|
|
|
|
// Close stops listening on the Unix address. Already accepted
|
|
// connections are not closed.
|
|
func (l *UnixListener) Close() error {
|
|
if !l.ok() {
|
|
return syscall.EINVAL
|
|
}
|
|
if err := l.close(); err != nil {
|
|
return &OpError{Op: "close", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Addr returns the listener's network address.
|
|
// The Addr returned is shared by all invocations of Addr, so
|
|
// do not modify it.
|
|
func (l *UnixListener) Addr() Addr { return l.fd.laddr }
|
|
|
|
// SetDeadline sets the deadline associated with the listener.
|
|
// A zero time value disables the deadline.
|
|
func (l *UnixListener) SetDeadline(t time.Time) error {
|
|
if !l.ok() {
|
|
return syscall.EINVAL
|
|
}
|
|
if err := l.fd.pfd.SetDeadline(t); err != nil {
|
|
return &OpError{Op: "set", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// File returns a copy of the underlying os.File, set to blocking
|
|
// mode. It is the caller's responsibility to close f when finished.
|
|
// Closing l does not affect f, and closing f does not affect l.
|
|
//
|
|
// The returned os.File's file descriptor is different from the
|
|
// connection's. Attempting to change properties of the original
|
|
// using this duplicate may or may not have the desired effect.
|
|
func (l *UnixListener) File() (f *os.File, err error) {
|
|
if !l.ok() {
|
|
return nil, syscall.EINVAL
|
|
}
|
|
f, err = l.file()
|
|
if err != nil {
|
|
err = &OpError{Op: "file", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
|
|
}
|
|
return
|
|
}
|
|
|
|
// ListenUnix acts like Listen for Unix networks.
|
|
//
|
|
// The network must be "unix" or "unixpacket".
|
|
func ListenUnix(network string, laddr *UnixAddr) (*UnixListener, error) {
|
|
switch network {
|
|
case "unix", "unixpacket":
|
|
default:
|
|
return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(network)}
|
|
}
|
|
if laddr == nil {
|
|
return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: errMissingAddress}
|
|
}
|
|
ln, err := listenUnix(context.Background(), network, laddr)
|
|
if err != nil {
|
|
return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: err}
|
|
}
|
|
return ln, nil
|
|
}
|
|
|
|
// ListenUnixgram acts like ListenPacket for Unix networks.
|
|
//
|
|
// The network must be "unixgram".
|
|
func ListenUnixgram(network string, laddr *UnixAddr) (*UnixConn, error) {
|
|
switch network {
|
|
case "unixgram":
|
|
default:
|
|
return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(network)}
|
|
}
|
|
if laddr == nil {
|
|
return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: nil, Err: errMissingAddress}
|
|
}
|
|
c, err := listenUnixgram(context.Background(), network, laddr)
|
|
if err != nil {
|
|
return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: err}
|
|
}
|
|
return c, nil
|
|
}
|