Add gcc.dg/parloops-exit-first-loop-alt-4.c
[official-gcc.git] / libgo / go / net / unixsock_posix.go
blob3c2e78bdca32502293f8f8f49886842b0044d1eb
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 // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
7 package net
9 import (
10 "errors"
11 "os"
12 "syscall"
13 "time"
16 func unixSocket(net string, laddr, raddr sockaddr, mode string, deadline time.Time) (*netFD, error) {
17 var sotype int
18 switch net {
19 case "unix":
20 sotype = syscall.SOCK_STREAM
21 case "unixgram":
22 sotype = syscall.SOCK_DGRAM
23 case "unixpacket":
24 sotype = syscall.SOCK_SEQPACKET
25 default:
26 return nil, UnknownNetworkError(net)
29 switch mode {
30 case "dial":
31 if laddr != nil && laddr.isWildcard() {
32 laddr = nil
34 if raddr != nil && raddr.isWildcard() {
35 raddr = nil
37 if raddr == nil && (sotype != syscall.SOCK_DGRAM || laddr == nil) {
38 return nil, errMissingAddress
40 case "listen":
41 default:
42 return nil, errors.New("unknown mode: " + mode)
45 fd, err := socket(net, syscall.AF_UNIX, sotype, 0, false, laddr, raddr, deadline)
46 if err != nil {
47 return nil, err
49 return fd, nil
52 func sockaddrToUnix(sa syscall.Sockaddr) Addr {
53 if s, ok := sa.(*syscall.SockaddrUnix); ok {
54 return &UnixAddr{Name: s.Name, Net: "unix"}
56 return nil
59 func sockaddrToUnixgram(sa syscall.Sockaddr) Addr {
60 if s, ok := sa.(*syscall.SockaddrUnix); ok {
61 return &UnixAddr{Name: s.Name, Net: "unixgram"}
63 return nil
66 func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr {
67 if s, ok := sa.(*syscall.SockaddrUnix); ok {
68 return &UnixAddr{Name: s.Name, Net: "unixpacket"}
70 return nil
73 func sotypeToNet(sotype int) string {
74 switch sotype {
75 case syscall.SOCK_STREAM:
76 return "unix"
77 case syscall.SOCK_DGRAM:
78 return "unixgram"
79 case syscall.SOCK_SEQPACKET:
80 return "unixpacket"
81 default:
82 panic("sotypeToNet unknown socket type")
86 func (a *UnixAddr) family() int {
87 return syscall.AF_UNIX
90 func (a *UnixAddr) isWildcard() bool {
91 return a == nil || a.Name == ""
94 func (a *UnixAddr) sockaddr(family int) (syscall.Sockaddr, error) {
95 if a == nil {
96 return nil, nil
98 return &syscall.SockaddrUnix{Name: a.Name}, nil
101 // UnixConn is an implementation of the Conn interface for connections
102 // to Unix domain sockets.
103 type UnixConn struct {
104 conn
107 func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{conn{fd}} }
109 // ReadFromUnix reads a packet from c, copying the payload into b. It
110 // returns the number of bytes copied into b and the source address of
111 // the packet.
113 // ReadFromUnix can be made to time out and return an error with
114 // Timeout() == true after a fixed time limit; see SetDeadline and
115 // SetReadDeadline.
116 func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) {
117 if !c.ok() {
118 return 0, nil, syscall.EINVAL
120 n, sa, err := c.fd.readFrom(b)
121 switch sa := sa.(type) {
122 case *syscall.SockaddrUnix:
123 if sa.Name != "" {
124 addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
127 return
130 // ReadFrom implements the PacketConn ReadFrom method.
131 func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
132 if !c.ok() {
133 return 0, nil, syscall.EINVAL
135 n, addr, err := c.ReadFromUnix(b)
136 return n, addr.toAddr(), err
139 // ReadMsgUnix reads a packet from c, copying the payload into b and
140 // the associated out-of-band data into oob. It returns the number of
141 // bytes copied into b, the number of bytes copied into oob, the flags
142 // that were set on the packet, and the source address of the packet.
143 func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
144 if !c.ok() {
145 return 0, 0, 0, nil, syscall.EINVAL
147 n, oobn, flags, sa, err := c.fd.readMsg(b, oob)
148 switch sa := sa.(type) {
149 case *syscall.SockaddrUnix:
150 if sa.Name != "" {
151 addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
154 return
157 // WriteToUnix writes a packet to addr via c, copying the payload from b.
159 // WriteToUnix can be made to time out and return an error with
160 // Timeout() == true after a fixed time limit; see SetDeadline and
161 // SetWriteDeadline. On packet-oriented connections, write timeouts
162 // are rare.
163 func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err error) {
164 if !c.ok() {
165 return 0, syscall.EINVAL
167 if c.fd.isConnected {
168 return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
170 if addr == nil {
171 return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
173 if addr.Net != sotypeToNet(c.fd.sotype) {
174 return 0, syscall.EAFNOSUPPORT
176 sa := &syscall.SockaddrUnix{Name: addr.Name}
177 return c.fd.writeTo(b, sa)
180 // WriteTo implements the PacketConn WriteTo method.
181 func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) {
182 if !c.ok() {
183 return 0, syscall.EINVAL
185 a, ok := addr.(*UnixAddr)
186 if !ok {
187 return 0, &OpError{"write", c.fd.net, addr, syscall.EINVAL}
189 return c.WriteToUnix(b, a)
192 // WriteMsgUnix writes a packet to addr via c, copying the payload
193 // from b and the associated out-of-band data from oob. It returns
194 // the number of payload and out-of-band bytes written.
195 func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
196 if !c.ok() {
197 return 0, 0, syscall.EINVAL
199 if c.fd.sotype == syscall.SOCK_DGRAM && c.fd.isConnected {
200 return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
202 if addr != nil {
203 if addr.Net != sotypeToNet(c.fd.sotype) {
204 return 0, 0, syscall.EAFNOSUPPORT
206 sa := &syscall.SockaddrUnix{Name: addr.Name}
207 return c.fd.writeMsg(b, oob, sa)
209 return c.fd.writeMsg(b, oob, nil)
212 // CloseRead shuts down the reading side of the Unix domain connection.
213 // Most callers should just use Close.
214 func (c *UnixConn) CloseRead() error {
215 if !c.ok() {
216 return syscall.EINVAL
218 return c.fd.closeRead()
221 // CloseWrite shuts down the writing side of the Unix domain connection.
222 // Most callers should just use Close.
223 func (c *UnixConn) CloseWrite() error {
224 if !c.ok() {
225 return syscall.EINVAL
227 return c.fd.closeWrite()
230 // DialUnix connects to the remote address raddr on the network net,
231 // which must be "unix", "unixgram" or "unixpacket". If laddr is not
232 // nil, it is used as the local address for the connection.
233 func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
234 switch net {
235 case "unix", "unixgram", "unixpacket":
236 default:
237 return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: UnknownNetworkError(net)}
239 return dialUnix(net, laddr, raddr, noDeadline)
242 func dialUnix(net string, laddr, raddr *UnixAddr, deadline time.Time) (*UnixConn, error) {
243 fd, err := unixSocket(net, laddr, raddr, "dial", deadline)
244 if err != nil {
245 return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: err}
247 return newUnixConn(fd), nil
250 // UnixListener is a Unix domain socket listener. Clients should
251 // typically use variables of type Listener instead of assuming Unix
252 // domain sockets.
253 type UnixListener struct {
254 fd *netFD
255 path string
258 // ListenUnix announces on the Unix domain socket laddr and returns a
259 // Unix listener. The network net must be "unix" or "unixpacket".
260 func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
261 switch net {
262 case "unix", "unixpacket":
263 default:
264 return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)}
266 if laddr == nil {
267 return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: errMissingAddress}
269 fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
270 if err != nil {
271 return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
273 return &UnixListener{fd, fd.laddr.String()}, nil
276 // AcceptUnix accepts the next incoming call and returns the new
277 // connection.
278 func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
279 if l == nil || l.fd == nil {
280 return nil, syscall.EINVAL
282 fd, err := l.fd.accept()
283 if err != nil {
284 return nil, err
286 c := newUnixConn(fd)
287 return c, nil
290 // Accept implements the Accept method in the Listener interface; it
291 // waits for the next call and returns a generic Conn.
292 func (l *UnixListener) Accept() (c Conn, err error) {
293 c1, err := l.AcceptUnix()
294 if err != nil {
295 return nil, err
297 return c1, nil
300 // Close stops listening on the Unix address. Already accepted
301 // connections are not closed.
302 func (l *UnixListener) Close() error {
303 if l == nil || l.fd == nil {
304 return syscall.EINVAL
307 // The operating system doesn't clean up
308 // the file that announcing created, so
309 // we have to clean it up ourselves.
310 // There's a race here--we can't know for
311 // sure whether someone else has come along
312 // and replaced our socket name already--
313 // but this sequence (remove then close)
314 // is at least compatible with the auto-remove
315 // sequence in ListenUnix. It's only non-Go
316 // programs that can mess us up.
317 if l.path[0] != '@' {
318 syscall.Unlink(l.path)
320 return l.fd.Close()
323 // Addr returns the listener's network address.
324 func (l *UnixListener) Addr() Addr { return l.fd.laddr }
326 // SetDeadline sets the deadline associated with the listener.
327 // A zero time value disables the deadline.
328 func (l *UnixListener) SetDeadline(t time.Time) (err error) {
329 if l == nil || l.fd == nil {
330 return syscall.EINVAL
332 return l.fd.setDeadline(t)
335 // File returns a copy of the underlying os.File, set to blocking
336 // mode. It is the caller's responsibility to close f when finished.
337 // Closing l does not affect f, and closing f does not affect l.
339 // The returned os.File's file descriptor is different from the
340 // connection's. Attempting to change properties of the original
341 // using this duplicate may or may not have the desired effect.
342 func (l *UnixListener) File() (f *os.File, err error) { return l.fd.dup() }
344 // ListenUnixgram listens for incoming Unix datagram packets addressed
345 // to the local address laddr. The network net must be "unixgram".
346 // The returned connection's ReadFrom and WriteTo methods can be used
347 // to receive and send packets with per-packet addressing.
348 func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
349 switch net {
350 case "unixgram":
351 default:
352 return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)}
354 if laddr == nil {
355 return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: errMissingAddress}
357 fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
358 if err != nil {
359 return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
361 return newUnixConn(fd), nil