* gcc.dg/guality/guality.exp: Skip on AIX.
[official-gcc.git] / libgo / go / net / file_unix.go
blob4c8403e40631ad89750b0c27361d877ffd958451
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 freebsd linux netbsd openbsd
7 package net
9 import (
10 "os"
11 "syscall"
14 func newFileFD(f *os.File) (*netFD, error) {
15 syscall.ForkLock.RLock()
16 fd, err := syscall.Dup(int(f.Fd()))
17 if err != nil {
18 syscall.ForkLock.RUnlock()
19 return nil, os.NewSyscallError("dup", err)
21 syscall.CloseOnExec(fd)
22 syscall.ForkLock.RUnlock()
23 if err = syscall.SetNonblock(fd, true); err != nil {
24 closesocket(fd)
25 return nil, err
28 sotype, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE)
29 if err != nil {
30 closesocket(fd)
31 return nil, os.NewSyscallError("getsockopt", err)
34 family := syscall.AF_UNSPEC
35 toAddr := sockaddrToTCP
36 lsa, _ := syscall.Getsockname(fd)
37 switch lsa.(type) {
38 default:
39 closesocket(fd)
40 return nil, syscall.EINVAL
41 case *syscall.SockaddrInet4:
42 family = syscall.AF_INET
43 if sotype == syscall.SOCK_DGRAM {
44 toAddr = sockaddrToUDP
45 } else if sotype == syscall.SOCK_RAW {
46 toAddr = sockaddrToIP
48 case *syscall.SockaddrInet6:
49 family = syscall.AF_INET6
50 if sotype == syscall.SOCK_DGRAM {
51 toAddr = sockaddrToUDP
52 } else if sotype == syscall.SOCK_RAW {
53 toAddr = sockaddrToIP
55 case *syscall.SockaddrUnix:
56 family = syscall.AF_UNIX
57 toAddr = sockaddrToUnix
58 if sotype == syscall.SOCK_DGRAM {
59 toAddr = sockaddrToUnixgram
60 } else if sotype == syscall.SOCK_SEQPACKET {
61 toAddr = sockaddrToUnixpacket
64 laddr := toAddr(lsa)
65 rsa, _ := syscall.Getpeername(fd)
66 raddr := toAddr(rsa)
68 netfd, err := newFD(fd, family, sotype, laddr.Network())
69 if err != nil {
70 closesocket(fd)
71 return nil, err
73 netfd.setAddr(laddr, raddr)
74 return netfd, nil
77 // FileConn returns a copy of the network connection corresponding to
78 // the open file f. It is the caller's responsibility to close f when
79 // finished. Closing c does not affect f, and closing f does not
80 // affect c.
81 func FileConn(f *os.File) (c Conn, err error) {
82 fd, err := newFileFD(f)
83 if err != nil {
84 return nil, err
86 switch fd.laddr.(type) {
87 case *TCPAddr:
88 return newTCPConn(fd), nil
89 case *UDPAddr:
90 return newUDPConn(fd), nil
91 case *IPAddr:
92 return newIPConn(fd), nil
93 case *UnixAddr:
94 return newUnixConn(fd), nil
96 fd.Close()
97 return nil, syscall.EINVAL
100 // FileListener returns a copy of the network listener corresponding
101 // to the open file f. It is the caller's responsibility to close l
102 // when finished. Closing l does not affect f, and closing f does not
103 // affect l.
104 func FileListener(f *os.File) (l Listener, err error) {
105 fd, err := newFileFD(f)
106 if err != nil {
107 return nil, err
109 switch laddr := fd.laddr.(type) {
110 case *TCPAddr:
111 return &TCPListener{fd}, nil
112 case *UnixAddr:
113 return &UnixListener{fd, laddr.Name}, nil
115 fd.Close()
116 return nil, syscall.EINVAL
119 // FilePacketConn returns a copy of the packet network connection
120 // corresponding to the open file f. It is the caller's
121 // responsibility to close f when finished. Closing c does not affect
122 // f, and closing f does not affect c.
123 func FilePacketConn(f *os.File) (c PacketConn, err error) {
124 fd, err := newFileFD(f)
125 if err != nil {
126 return nil, err
128 switch fd.laddr.(type) {
129 case *UDPAddr:
130 return newUDPConn(fd), nil
131 case *UnixAddr:
132 return newUnixConn(fd), nil
134 fd.Close()
135 return nil, syscall.EINVAL