libgo: Update to Go 1.3 release.
[official-gcc.git] / libgo / go / net / file_unix.go
blob07b3ecf62637f44d726a674109f9fa01696974b6
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
7 package net
9 import (
10 "os"
11 "syscall"
14 func newFileFD(f *os.File) (*netFD, error) {
15 fd, err := dupCloseOnExec(int(f.Fd()))
16 if err != nil {
17 return nil, os.NewSyscallError("dup", err)
20 if err = syscall.SetNonblock(fd, true); err != nil {
21 closesocket(fd)
22 return nil, err
25 sotype, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE)
26 if err != nil {
27 closesocket(fd)
28 return nil, os.NewSyscallError("getsockopt", err)
31 family := syscall.AF_UNSPEC
32 toAddr := sockaddrToTCP
33 lsa, _ := syscall.Getsockname(fd)
34 switch lsa.(type) {
35 default:
36 closesocket(fd)
37 return nil, syscall.EINVAL
38 case *syscall.SockaddrInet4:
39 family = syscall.AF_INET
40 if sotype == syscall.SOCK_DGRAM {
41 toAddr = sockaddrToUDP
42 } else if sotype == syscall.SOCK_RAW {
43 toAddr = sockaddrToIP
45 case *syscall.SockaddrInet6:
46 family = syscall.AF_INET6
47 if sotype == syscall.SOCK_DGRAM {
48 toAddr = sockaddrToUDP
49 } else if sotype == syscall.SOCK_RAW {
50 toAddr = sockaddrToIP
52 case *syscall.SockaddrUnix:
53 family = syscall.AF_UNIX
54 toAddr = sockaddrToUnix
55 if sotype == syscall.SOCK_DGRAM {
56 toAddr = sockaddrToUnixgram
57 } else if sotype == syscall.SOCK_SEQPACKET {
58 toAddr = sockaddrToUnixpacket
61 laddr := toAddr(lsa)
62 rsa, _ := syscall.Getpeername(fd)
63 raddr := toAddr(rsa)
65 netfd, err := newFD(fd, family, sotype, laddr.Network())
66 if err != nil {
67 closesocket(fd)
68 return nil, err
70 if err := netfd.init(); err != nil {
71 netfd.Close()
72 return nil, err
74 netfd.setAddr(laddr, raddr)
75 return netfd, nil
78 // FileConn returns a copy of the network connection corresponding to
79 // the open file f. It is the caller's responsibility to close f when
80 // finished. Closing c does not affect f, and closing f does not
81 // affect c.
82 func FileConn(f *os.File) (c Conn, err error) {
83 fd, err := newFileFD(f)
84 if err != nil {
85 return nil, err
87 switch fd.laddr.(type) {
88 case *TCPAddr:
89 return newTCPConn(fd), nil
90 case *UDPAddr:
91 return newUDPConn(fd), nil
92 case *IPAddr:
93 return newIPConn(fd), nil
94 case *UnixAddr:
95 return newUnixConn(fd), nil
97 fd.Close()
98 return nil, syscall.EINVAL
101 // FileListener returns a copy of the network listener corresponding
102 // to the open file f. It is the caller's responsibility to close l
103 // when finished. Closing l does not affect f, and closing f does not
104 // affect l.
105 func FileListener(f *os.File) (l Listener, err error) {
106 fd, err := newFileFD(f)
107 if err != nil {
108 return nil, err
110 switch laddr := fd.laddr.(type) {
111 case *TCPAddr:
112 return &TCPListener{fd}, nil
113 case *UnixAddr:
114 return &UnixListener{fd, laddr.Name}, nil
116 fd.Close()
117 return nil, syscall.EINVAL
120 // FilePacketConn returns a copy of the packet network connection
121 // corresponding to the open file f. It is the caller's
122 // responsibility to close f when finished. Closing c does not affect
123 // f, and closing f does not affect c.
124 func FilePacketConn(f *os.File) (c PacketConn, err error) {
125 fd, err := newFileFD(f)
126 if err != nil {
127 return nil, err
129 switch fd.laddr.(type) {
130 case *UDPAddr:
131 return newUDPConn(fd), nil
132 case *IPAddr:
133 return newIPConn(fd), nil
134 case *UnixAddr:
135 return newUnixConn(fd), nil
137 fd.Close()
138 return nil, syscall.EINVAL