libgo: update to Go 1.11
[official-gcc.git] / libgo / go / net / unixsock.go
blob3ae62f6a8b84afadb7a296f66f364634675fca56
1 // Copyright 2009 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 package net
7 import (
8 "context"
9 "os"
10 "sync"
11 "syscall"
12 "time"
15 // BUG(mikio): On JS, NaCl, Plan 9 and Windows, methods and functions
16 // related to UnixConn and UnixListener are not implemented.
18 // UnixAddr represents the address of a Unix domain socket end point.
19 type UnixAddr struct {
20 Name string
21 Net string
24 // Network returns the address's network name, "unix", "unixgram" or
25 // "unixpacket".
26 func (a *UnixAddr) Network() string {
27 return a.Net
30 func (a *UnixAddr) String() string {
31 if a == nil {
32 return "<nil>"
34 return a.Name
37 func (a *UnixAddr) isWildcard() bool {
38 return a == nil || a.Name == ""
41 func (a *UnixAddr) opAddr() Addr {
42 if a == nil {
43 return nil
45 return a
48 // ResolveUnixAddr returns an address of Unix domain socket end point.
50 // The network must be a Unix network name.
52 // See func Dial for a description of the network and address
53 // parameters.
54 func ResolveUnixAddr(network, address string) (*UnixAddr, error) {
55 switch network {
56 case "unix", "unixgram", "unixpacket":
57 return &UnixAddr{Name: address, Net: network}, nil
58 default:
59 return nil, UnknownNetworkError(network)
63 // UnixConn is an implementation of the Conn interface for connections
64 // to Unix domain sockets.
65 type UnixConn struct {
66 conn
69 // SyscallConn returns a raw network connection.
70 // This implements the syscall.Conn interface.
71 func (c *UnixConn) SyscallConn() (syscall.RawConn, error) {
72 if !c.ok() {
73 return nil, syscall.EINVAL
75 return newRawConn(c.fd)
78 // CloseRead shuts down the reading side of the Unix domain connection.
79 // Most callers should just use Close.
80 func (c *UnixConn) CloseRead() error {
81 if !c.ok() {
82 return syscall.EINVAL
84 if err := c.fd.closeRead(); err != nil {
85 return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
87 return nil
90 // CloseWrite shuts down the writing side of the Unix domain connection.
91 // Most callers should just use Close.
92 func (c *UnixConn) CloseWrite() error {
93 if !c.ok() {
94 return syscall.EINVAL
96 if err := c.fd.closeWrite(); err != nil {
97 return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
99 return nil
102 // ReadFromUnix acts like ReadFrom but returns a UnixAddr.
103 func (c *UnixConn) ReadFromUnix(b []byte) (int, *UnixAddr, error) {
104 if !c.ok() {
105 return 0, nil, syscall.EINVAL
107 n, addr, err := c.readFrom(b)
108 if err != nil {
109 err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
111 return n, addr, err
114 // ReadFrom implements the PacketConn ReadFrom method.
115 func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
116 if !c.ok() {
117 return 0, nil, syscall.EINVAL
119 n, addr, err := c.readFrom(b)
120 if err != nil {
121 err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
123 if addr == nil {
124 return n, nil, err
126 return n, addr, err
129 // ReadMsgUnix reads a message from c, copying the payload into b and
130 // the associated out-of-band data into oob. It returns the number of
131 // bytes copied into b, the number of bytes copied into oob, the flags
132 // that were set on the message and the source address of the message.
134 // Note that if len(b) == 0 and len(oob) > 0, this function will still
135 // read (and discard) 1 byte from the connection.
136 func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
137 if !c.ok() {
138 return 0, 0, 0, nil, syscall.EINVAL
140 n, oobn, flags, addr, err = c.readMsg(b, oob)
141 if err != nil {
142 err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
144 return
147 // WriteToUnix acts like WriteTo but takes a UnixAddr.
148 func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (int, error) {
149 if !c.ok() {
150 return 0, syscall.EINVAL
152 n, err := c.writeTo(b, addr)
153 if err != nil {
154 err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
156 return n, err
159 // WriteTo implements the PacketConn WriteTo method.
160 func (c *UnixConn) WriteTo(b []byte, addr Addr) (int, error) {
161 if !c.ok() {
162 return 0, syscall.EINVAL
164 a, ok := addr.(*UnixAddr)
165 if !ok {
166 return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
168 n, err := c.writeTo(b, a)
169 if err != nil {
170 err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: a.opAddr(), Err: err}
172 return n, err
175 // WriteMsgUnix writes a message to addr via c, copying the payload
176 // from b and the associated out-of-band data from oob. It returns the
177 // number of payload and out-of-band bytes written.
179 // Note that if len(b) == 0 and len(oob) > 0, this function will still
180 // write 1 byte to the connection.
181 func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
182 if !c.ok() {
183 return 0, 0, syscall.EINVAL
185 n, oobn, err = c.writeMsg(b, oob, addr)
186 if err != nil {
187 err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
189 return
192 func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{conn{fd}} }
194 // DialUnix acts like Dial for Unix networks.
196 // The network must be a Unix network name; see func Dial for details.
198 // If laddr is non-nil, it is used as the local address for the
199 // connection.
200 func DialUnix(network string, laddr, raddr *UnixAddr) (*UnixConn, error) {
201 switch network {
202 case "unix", "unixgram", "unixpacket":
203 default:
204 return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(network)}
206 sd := &sysDialer{network: network, address: raddr.String()}
207 c, err := sd.dialUnix(context.Background(), laddr, raddr)
208 if err != nil {
209 return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
211 return c, nil
214 // UnixListener is a Unix domain socket listener. Clients should
215 // typically use variables of type Listener instead of assuming Unix
216 // domain sockets.
217 type UnixListener struct {
218 fd *netFD
219 path string
220 unlink bool
221 unlinkOnce sync.Once
224 func (ln *UnixListener) ok() bool { return ln != nil && ln.fd != nil }
226 // SyscallConn returns a raw network connection.
227 // This implements the syscall.Conn interface.
229 // The returned RawConn only supports calling Control. Read and
230 // Write return an error.
231 func (l *UnixListener) SyscallConn() (syscall.RawConn, error) {
232 if !l.ok() {
233 return nil, syscall.EINVAL
235 return newRawListener(l.fd)
238 // AcceptUnix accepts the next incoming call and returns the new
239 // connection.
240 func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
241 if !l.ok() {
242 return nil, syscall.EINVAL
244 c, err := l.accept()
245 if err != nil {
246 return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
248 return c, nil
251 // Accept implements the Accept method in the Listener interface.
252 // Returned connections will be of type *UnixConn.
253 func (l *UnixListener) Accept() (Conn, error) {
254 if !l.ok() {
255 return nil, syscall.EINVAL
257 c, err := l.accept()
258 if err != nil {
259 return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
261 return c, nil
264 // Close stops listening on the Unix address. Already accepted
265 // connections are not closed.
266 func (l *UnixListener) Close() error {
267 if !l.ok() {
268 return syscall.EINVAL
270 if err := l.close(); err != nil {
271 return &OpError{Op: "close", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
273 return nil
276 // Addr returns the listener's network address.
277 // The Addr returned is shared by all invocations of Addr, so
278 // do not modify it.
279 func (l *UnixListener) Addr() Addr { return l.fd.laddr }
281 // SetDeadline sets the deadline associated with the listener.
282 // A zero time value disables the deadline.
283 func (l *UnixListener) SetDeadline(t time.Time) error {
284 if !l.ok() {
285 return syscall.EINVAL
287 if err := l.fd.pfd.SetDeadline(t); err != nil {
288 return &OpError{Op: "set", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
290 return nil
293 // File returns a copy of the underlying os.File.
294 // It is the caller's responsibility to close f when finished.
295 // Closing l does not affect f, and closing f does not affect l.
297 // The returned os.File's file descriptor is different from the
298 // connection's. Attempting to change properties of the original
299 // using this duplicate may or may not have the desired effect.
300 func (l *UnixListener) File() (f *os.File, err error) {
301 if !l.ok() {
302 return nil, syscall.EINVAL
304 f, err = l.file()
305 if err != nil {
306 err = &OpError{Op: "file", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
308 return
311 // ListenUnix acts like Listen for Unix networks.
313 // The network must be "unix" or "unixpacket".
314 func ListenUnix(network string, laddr *UnixAddr) (*UnixListener, error) {
315 switch network {
316 case "unix", "unixpacket":
317 default:
318 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(network)}
320 if laddr == nil {
321 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: errMissingAddress}
323 sl := &sysListener{network: network, address: laddr.String()}
324 ln, err := sl.listenUnix(context.Background(), laddr)
325 if err != nil {
326 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: err}
328 return ln, nil
331 // ListenUnixgram acts like ListenPacket for Unix networks.
333 // The network must be "unixgram".
334 func ListenUnixgram(network string, laddr *UnixAddr) (*UnixConn, error) {
335 switch network {
336 case "unixgram":
337 default:
338 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(network)}
340 if laddr == nil {
341 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: nil, Err: errMissingAddress}
343 sl := &sysListener{network: network, address: laddr.String()}
344 c, err := sl.listenUnixgram(context.Background(), laddr)
345 if err != nil {
346 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: err}
348 return c, nil