testsuite: Skip 90020.c on AIX.
[official-gcc.git] / libgo / go / net / unixsock.go
blobb38438c11a82b0fb439b025d9430c1912926e9d4
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 and Plan 9, methods and functions related
16 // to UnixConn and UnixListener are not implemented.
18 // BUG(mikio): On Windows, methods and functions related to UnixConn
19 // and UnixListener don't work for "unixgram" and "unixpacket".
21 // UnixAddr represents the address of a Unix domain socket end point.
22 type UnixAddr struct {
23 Name string
24 Net string
27 // Network returns the address's network name, "unix", "unixgram" or
28 // "unixpacket".
29 func (a *UnixAddr) Network() string {
30 return a.Net
33 func (a *UnixAddr) String() string {
34 if a == nil {
35 return "<nil>"
37 return a.Name
40 func (a *UnixAddr) isWildcard() bool {
41 return a == nil || a.Name == ""
44 func (a *UnixAddr) opAddr() Addr {
45 if a == nil {
46 return nil
48 return a
51 // ResolveUnixAddr returns an address of Unix domain socket end point.
53 // The network must be a Unix network name.
55 // See func Dial for a description of the network and address
56 // parameters.
57 func ResolveUnixAddr(network, address string) (*UnixAddr, error) {
58 switch network {
59 case "unix", "unixgram", "unixpacket":
60 return &UnixAddr{Name: address, Net: network}, nil
61 default:
62 return nil, UnknownNetworkError(network)
66 // UnixConn is an implementation of the Conn interface for connections
67 // to Unix domain sockets.
68 type UnixConn struct {
69 conn
72 // SyscallConn returns a raw network connection.
73 // This implements the syscall.Conn interface.
74 func (c *UnixConn) SyscallConn() (syscall.RawConn, error) {
75 if !c.ok() {
76 return nil, syscall.EINVAL
78 return newRawConn(c.fd)
81 // CloseRead shuts down the reading side of the Unix domain connection.
82 // Most callers should just use Close.
83 func (c *UnixConn) CloseRead() error {
84 if !c.ok() {
85 return syscall.EINVAL
87 if err := c.fd.closeRead(); err != nil {
88 return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
90 return nil
93 // CloseWrite shuts down the writing side of the Unix domain connection.
94 // Most callers should just use Close.
95 func (c *UnixConn) CloseWrite() error {
96 if !c.ok() {
97 return syscall.EINVAL
99 if err := c.fd.closeWrite(); err != nil {
100 return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
102 return nil
105 // ReadFromUnix acts like ReadFrom but returns a UnixAddr.
106 func (c *UnixConn) ReadFromUnix(b []byte) (int, *UnixAddr, error) {
107 if !c.ok() {
108 return 0, nil, syscall.EINVAL
110 n, addr, err := c.readFrom(b)
111 if err != nil {
112 err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
114 return n, addr, err
117 // ReadFrom implements the PacketConn ReadFrom method.
118 func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
119 if !c.ok() {
120 return 0, nil, syscall.EINVAL
122 n, addr, err := c.readFrom(b)
123 if err != nil {
124 err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
126 if addr == nil {
127 return n, nil, err
129 return n, addr, err
132 // ReadMsgUnix reads a message from c, copying the payload into b and
133 // the associated out-of-band data into oob. It returns the number of
134 // bytes copied into b, the number of bytes copied into oob, the flags
135 // that were set on the message and the source address of the message.
137 // Note that if len(b) == 0 and len(oob) > 0, this function will still
138 // read (and discard) 1 byte from the connection.
139 func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
140 if !c.ok() {
141 return 0, 0, 0, nil, syscall.EINVAL
143 n, oobn, flags, addr, err = c.readMsg(b, oob)
144 if err != nil {
145 err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
147 return
150 // WriteToUnix acts like WriteTo but takes a UnixAddr.
151 func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (int, error) {
152 if !c.ok() {
153 return 0, syscall.EINVAL
155 n, err := c.writeTo(b, addr)
156 if err != nil {
157 err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
159 return n, err
162 // WriteTo implements the PacketConn WriteTo method.
163 func (c *UnixConn) WriteTo(b []byte, addr Addr) (int, error) {
164 if !c.ok() {
165 return 0, syscall.EINVAL
167 a, ok := addr.(*UnixAddr)
168 if !ok {
169 return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
171 n, err := c.writeTo(b, a)
172 if err != nil {
173 err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: a.opAddr(), Err: err}
175 return n, err
178 // WriteMsgUnix writes a message to addr via c, copying the payload
179 // from b and the associated out-of-band data from oob. It returns the
180 // number of payload and out-of-band bytes written.
182 // Note that if len(b) == 0 and len(oob) > 0, this function will still
183 // write 1 byte to the connection.
184 func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
185 if !c.ok() {
186 return 0, 0, syscall.EINVAL
188 n, oobn, err = c.writeMsg(b, oob, addr)
189 if err != nil {
190 err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
192 return
195 func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{conn{fd}} }
197 // DialUnix acts like Dial for Unix networks.
199 // The network must be a Unix network name; see func Dial for details.
201 // If laddr is non-nil, it is used as the local address for the
202 // connection.
203 func DialUnix(network string, laddr, raddr *UnixAddr) (*UnixConn, error) {
204 switch network {
205 case "unix", "unixgram", "unixpacket":
206 default:
207 return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(network)}
209 sd := &sysDialer{network: network, address: raddr.String()}
210 c, err := sd.dialUnix(context.Background(), laddr, raddr)
211 if err != nil {
212 return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
214 return c, nil
217 // UnixListener is a Unix domain socket listener. Clients should
218 // typically use variables of type Listener instead of assuming Unix
219 // domain sockets.
220 type UnixListener struct {
221 fd *netFD
222 path string
223 unlink bool
224 unlinkOnce sync.Once
227 func (ln *UnixListener) ok() bool { return ln != nil && ln.fd != nil }
229 // SyscallConn returns a raw network connection.
230 // This implements the syscall.Conn interface.
232 // The returned RawConn only supports calling Control. Read and
233 // Write return an error.
234 func (l *UnixListener) SyscallConn() (syscall.RawConn, error) {
235 if !l.ok() {
236 return nil, syscall.EINVAL
238 return newRawListener(l.fd)
241 // AcceptUnix accepts the next incoming call and returns the new
242 // connection.
243 func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
244 if !l.ok() {
245 return nil, syscall.EINVAL
247 c, err := l.accept()
248 if err != nil {
249 return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
251 return c, nil
254 // Accept implements the Accept method in the Listener interface.
255 // Returned connections will be of type *UnixConn.
256 func (l *UnixListener) Accept() (Conn, error) {
257 if !l.ok() {
258 return nil, syscall.EINVAL
260 c, err := l.accept()
261 if err != nil {
262 return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
264 return c, nil
267 // Close stops listening on the Unix address. Already accepted
268 // connections are not closed.
269 func (l *UnixListener) Close() error {
270 if !l.ok() {
271 return syscall.EINVAL
273 if err := l.close(); err != nil {
274 return &OpError{Op: "close", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
276 return nil
279 // Addr returns the listener's network address.
280 // The Addr returned is shared by all invocations of Addr, so
281 // do not modify it.
282 func (l *UnixListener) Addr() Addr { return l.fd.laddr }
284 // SetDeadline sets the deadline associated with the listener.
285 // A zero time value disables the deadline.
286 func (l *UnixListener) SetDeadline(t time.Time) error {
287 if !l.ok() {
288 return syscall.EINVAL
290 if err := l.fd.pfd.SetDeadline(t); err != nil {
291 return &OpError{Op: "set", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
293 return nil
296 // File returns a copy of the underlying os.File.
297 // It is the caller's responsibility to close f when finished.
298 // Closing l does not affect f, and closing f does not affect l.
300 // The returned os.File's file descriptor is different from the
301 // connection's. Attempting to change properties of the original
302 // using this duplicate may or may not have the desired effect.
303 func (l *UnixListener) File() (f *os.File, err error) {
304 if !l.ok() {
305 return nil, syscall.EINVAL
307 f, err = l.file()
308 if err != nil {
309 err = &OpError{Op: "file", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
311 return
314 // ListenUnix acts like Listen for Unix networks.
316 // The network must be "unix" or "unixpacket".
317 func ListenUnix(network string, laddr *UnixAddr) (*UnixListener, error) {
318 switch network {
319 case "unix", "unixpacket":
320 default:
321 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(network)}
323 if laddr == nil {
324 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: errMissingAddress}
326 sl := &sysListener{network: network, address: laddr.String()}
327 ln, err := sl.listenUnix(context.Background(), laddr)
328 if err != nil {
329 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: err}
331 return ln, nil
334 // ListenUnixgram acts like ListenPacket for Unix networks.
336 // The network must be "unixgram".
337 func ListenUnixgram(network string, laddr *UnixAddr) (*UnixConn, error) {
338 switch network {
339 case "unixgram":
340 default:
341 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(network)}
343 if laddr == nil {
344 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: nil, Err: errMissingAddress}
346 sl := &sysListener{network: network, address: laddr.String()}
347 c, err := sl.listenUnixgram(context.Background(), laddr)
348 if err != nil {
349 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: err}
351 return c, nil