github.com/remobjects/goldbaselibrary@v0.0.0-20230924164425-d458680a936b/Source/Gold/net/file_unix.go (about) 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. 4 5 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris 6 7 package net 8 9 import ( 10 "internal/poll" 11 "os" 12 "syscall" 13 ) 14 15 func dupSocket(f *os.File) (int, error) { 16 s, call, err := poll.DupCloseOnExec(int(f.Fd())) 17 if err != nil { 18 if call != "" { 19 err = os.NewSyscallError(call, err) 20 } 21 return -1, err 22 } 23 if err := syscall.SetNonblock(s, true); err != nil { 24 poll.CloseFunc(s) 25 return -1, os.NewSyscallError("setnonblock", err) 26 } 27 return s, nil 28 } 29 30 func newFileFD(f *os.File) (*netFD, error) { 31 s, err := dupSocket(f) 32 if err != nil { 33 return nil, err 34 } 35 family := syscall.AF_UNSPEC 36 sotype, err := syscall.GetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_TYPE) 37 if err != nil { 38 poll.CloseFunc(s) 39 return nil, os.NewSyscallError("getsockopt", err) 40 } 41 lsa, _ := syscall.Getsockname(s) 42 rsa, _ := syscall.Getpeername(s) 43 switch lsa.(type) { 44 case *syscall.SockaddrInet4: 45 family = syscall.AF_INET 46 case *syscall.SockaddrInet6: 47 family = syscall.AF_INET6 48 case *syscall.SockaddrUnix: 49 family = syscall.AF_UNIX 50 default: 51 poll.CloseFunc(s) 52 return nil, syscall.EPROTONOSUPPORT 53 } 54 fd, err := newFD(s, family, sotype, "") 55 if err != nil { 56 poll.CloseFunc(s) 57 return nil, err 58 } 59 laddr := fd.addrFunc()(lsa) 60 raddr := fd.addrFunc()(rsa) 61 fd.net = laddr.Network() 62 if err := fd.init(); err != nil { 63 fd.Close() 64 return nil, err 65 } 66 fd.setAddr(laddr, raddr) 67 return fd, nil 68 } 69 70 func fileConn(f *os.File) (Conn, error) { 71 fd, err := newFileFD(f) 72 if err != nil { 73 return nil, err 74 } 75 switch fd.laddr.(type) { 76 case *TCPAddr: 77 return newTCPConn(fd), nil 78 case *UDPAddr: 79 return newUDPConn(fd), nil 80 case *IPAddr: 81 return newIPConn(fd), nil 82 case *UnixAddr: 83 return newUnixConn(fd), nil 84 } 85 fd.Close() 86 return nil, syscall.EINVAL 87 } 88 89 func fileListener(f *os.File) (Listener, error) { 90 fd, err := newFileFD(f) 91 if err != nil { 92 return nil, err 93 } 94 switch laddr := fd.laddr.(type) { 95 case *TCPAddr: 96 return &TCPListener{fd: fd}, nil 97 case *UnixAddr: 98 return &UnixListener{fd: fd, path: laddr.Name, unlink: false}, nil 99 } 100 fd.Close() 101 return nil, syscall.EINVAL 102 } 103 104 func filePacketConn(f *os.File) (PacketConn, error) { 105 fd, err := newFileFD(f) 106 if err != nil { 107 return nil, err 108 } 109 switch fd.laddr.(type) { 110 case *UDPAddr: 111 return newUDPConn(fd), nil 112 case *IPAddr: 113 return newIPConn(fd), nil 114 case *UnixAddr: 115 return newUnixConn(fd), nil 116 } 117 fd.Close() 118 return nil, syscall.EINVAL 119 }