Retro68/gcc/libgo/go/net/file_unix.go

116 lines
2.4 KiB
Go
Raw Normal View History

2012-03-27 23:13:14 +00:00
// Copyright 2011 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.
2015-08-28 15:33:40 +00:00
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
2012-03-27 23:13:14 +00:00
package net
import (
"os"
"syscall"
)
2017-04-10 11:32:00 +00:00
func dupSocket(f *os.File) (int, error) {
s, err := dupCloseOnExec(int(f.Fd()))
2012-03-27 23:13:14 +00:00
if err != nil {
2017-04-10 11:32:00 +00:00
return -1, err
}
if err := syscall.SetNonblock(s, true); err != nil {
closeFunc(s)
return -1, os.NewSyscallError("setnonblock", err)
2012-03-27 23:13:14 +00:00
}
2017-04-10 11:32:00 +00:00
return s, nil
}
2012-03-27 23:13:14 +00:00
2017-04-10 11:32:00 +00:00
func newFileFD(f *os.File) (*netFD, error) {
s, err := dupSocket(f)
if err != nil {
2014-09-21 17:33:12 +00:00
return nil, err
}
2017-04-10 11:32:00 +00:00
family := syscall.AF_UNSPEC
sotype, err := syscall.GetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_TYPE)
2012-03-27 23:13:14 +00:00
if err != nil {
2017-04-10 11:32:00 +00:00
closeFunc(s)
2012-03-27 23:13:14 +00:00
return nil, os.NewSyscallError("getsockopt", err)
}
2017-04-10 11:32:00 +00:00
lsa, _ := syscall.Getsockname(s)
rsa, _ := syscall.Getpeername(s)
2014-09-21 17:33:12 +00:00
switch lsa.(type) {
2012-03-27 23:13:14 +00:00
case *syscall.SockaddrInet4:
family = syscall.AF_INET
case *syscall.SockaddrInet6:
family = syscall.AF_INET6
case *syscall.SockaddrUnix:
family = syscall.AF_UNIX
2017-04-10 11:32:00 +00:00
default:
closeFunc(s)
return nil, syscall.EPROTONOSUPPORT
2012-03-27 23:13:14 +00:00
}
2017-04-10 11:32:00 +00:00
fd, err := newFD(s, family, sotype, "")
2012-03-27 23:13:14 +00:00
if err != nil {
2017-04-10 11:32:00 +00:00
closeFunc(s)
2014-09-21 17:33:12 +00:00
return nil, err
}
2017-04-10 11:32:00 +00:00
laddr := fd.addrFunc()(lsa)
raddr := fd.addrFunc()(rsa)
fd.net = laddr.Network()
if err := fd.init(); err != nil {
fd.Close()
2012-03-27 23:13:14 +00:00
return nil, err
}
2017-04-10 11:32:00 +00:00
fd.setAddr(laddr, raddr)
return fd, nil
2012-03-27 23:13:14 +00:00
}
2017-04-10 11:32:00 +00:00
func fileConn(f *os.File) (Conn, error) {
2012-03-27 23:13:14 +00:00
fd, err := newFileFD(f)
if err != nil {
return nil, err
}
switch fd.laddr.(type) {
case *TCPAddr:
return newTCPConn(fd), nil
case *UDPAddr:
return newUDPConn(fd), nil
case *IPAddr:
return newIPConn(fd), nil
2014-09-21 17:33:12 +00:00
case *UnixAddr:
return newUnixConn(fd), nil
2012-03-27 23:13:14 +00:00
}
fd.Close()
return nil, syscall.EINVAL
}
2017-04-10 11:32:00 +00:00
func fileListener(f *os.File) (Listener, error) {
2012-03-27 23:13:14 +00:00
fd, err := newFileFD(f)
if err != nil {
return nil, err
}
switch laddr := fd.laddr.(type) {
case *TCPAddr:
return &TCPListener{fd}, nil
case *UnixAddr:
2017-04-10 11:32:00 +00:00
return &UnixListener{fd: fd, path: laddr.Name, unlink: false}, nil
2012-03-27 23:13:14 +00:00
}
fd.Close()
return nil, syscall.EINVAL
}
2017-04-10 11:32:00 +00:00
func filePacketConn(f *os.File) (PacketConn, error) {
2012-03-27 23:13:14 +00:00
fd, err := newFileFD(f)
if err != nil {
return nil, err
}
switch fd.laddr.(type) {
case *UDPAddr:
return newUDPConn(fd), nil
2015-08-28 15:33:40 +00:00
case *IPAddr:
return newIPConn(fd), nil
2012-03-27 23:13:14 +00:00
case *UnixAddr:
return newUnixConn(fd), nil
}
fd.Close()
return nil, syscall.EINVAL
}