remove unused files
[platform/upstream/gcc48.git] / libgo / go / net / unixsock_posix.go
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.
4
5 // +build darwin freebsd linux netbsd openbsd windows
6
7 package net
8
9 import (
10         "errors"
11         "os"
12         "syscall"
13         "time"
14 )
15
16 func (a *UnixAddr) isUnnamed() bool {
17         if a == nil || a.Name == "" {
18                 return true
19         }
20         return false
21 }
22
23 func unixSocket(net string, laddr, raddr *UnixAddr, mode string, deadline time.Time) (*netFD, error) {
24         var sotype int
25         switch net {
26         case "unix":
27                 sotype = syscall.SOCK_STREAM
28         case "unixgram":
29                 sotype = syscall.SOCK_DGRAM
30         case "unixpacket":
31                 sotype = syscall.SOCK_SEQPACKET
32         default:
33                 return nil, UnknownNetworkError(net)
34         }
35
36         var la, ra syscall.Sockaddr
37         switch mode {
38         case "dial":
39                 if !laddr.isUnnamed() {
40                         la = &syscall.SockaddrUnix{Name: laddr.Name}
41                 }
42                 if raddr != nil {
43                         ra = &syscall.SockaddrUnix{Name: raddr.Name}
44                 } else if sotype != syscall.SOCK_DGRAM || laddr.isUnnamed() {
45                         return nil, &OpError{Op: mode, Net: net, Err: errMissingAddress}
46                 }
47         case "listen":
48                 la = &syscall.SockaddrUnix{Name: laddr.Name}
49         default:
50                 return nil, errors.New("unknown mode: " + mode)
51         }
52
53         f := sockaddrToUnix
54         if sotype == syscall.SOCK_DGRAM {
55                 f = sockaddrToUnixgram
56         } else if sotype == syscall.SOCK_SEQPACKET {
57                 f = sockaddrToUnixpacket
58         }
59
60         fd, err := socket(net, syscall.AF_UNIX, sotype, 0, false, la, ra, deadline, f)
61         if err != nil {
62                 goto error
63         }
64         return fd, nil
65
66 error:
67         addr := raddr
68         switch mode {
69         case "listen":
70                 addr = laddr
71         }
72         return nil, &OpError{Op: mode, Net: net, Addr: addr, Err: err}
73 }
74
75 func sockaddrToUnix(sa syscall.Sockaddr) Addr {
76         if s, ok := sa.(*syscall.SockaddrUnix); ok {
77                 return &UnixAddr{Name: s.Name, Net: "unix"}
78         }
79         return nil
80 }
81
82 func sockaddrToUnixgram(sa syscall.Sockaddr) Addr {
83         if s, ok := sa.(*syscall.SockaddrUnix); ok {
84                 return &UnixAddr{Name: s.Name, Net: "unixgram"}
85         }
86         return nil
87 }
88
89 func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr {
90         if s, ok := sa.(*syscall.SockaddrUnix); ok {
91                 return &UnixAddr{Name: s.Name, Net: "unixpacket"}
92         }
93         return nil
94 }
95
96 func sotypeToNet(sotype int) string {
97         switch sotype {
98         case syscall.SOCK_STREAM:
99                 return "unix"
100         case syscall.SOCK_DGRAM:
101                 return "unixgram"
102         case syscall.SOCK_SEQPACKET:
103                 return "unixpacket"
104         default:
105                 panic("sotypeToNet unknown socket type")
106         }
107 }
108
109 // UnixConn is an implementation of the Conn interface for connections
110 // to Unix domain sockets.
111 type UnixConn struct {
112         conn
113 }
114
115 func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{conn{fd}} }
116
117 // ReadFromUnix reads a packet from c, copying the payload into b.  It
118 // returns the number of bytes copied into b and the source address of
119 // the packet.
120 //
121 // ReadFromUnix can be made to time out and return an error with
122 // Timeout() == true after a fixed time limit; see SetDeadline and
123 // SetReadDeadline.
124 func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) {
125         if !c.ok() {
126                 return 0, nil, syscall.EINVAL
127         }
128         n, sa, err := c.fd.ReadFrom(b)
129         switch sa := sa.(type) {
130         case *syscall.SockaddrUnix:
131                 if sa.Name != "" {
132                         addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
133                 }
134         }
135         return
136 }
137
138 // ReadFrom implements the PacketConn ReadFrom method.
139 func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
140         if !c.ok() {
141                 return 0, nil, syscall.EINVAL
142         }
143         n, addr, err := c.ReadFromUnix(b)
144         return n, addr.toAddr(), err
145 }
146
147 // ReadMsgUnix reads a packet from c, copying the payload into b and
148 // the associated out-of-band data into oob.  It returns the number of
149 // bytes copied into b, the number of bytes copied into oob, the flags
150 // that were set on the packet, and the source address of the packet.
151 func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
152         if !c.ok() {
153                 return 0, 0, 0, nil, syscall.EINVAL
154         }
155         n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob)
156         switch sa := sa.(type) {
157         case *syscall.SockaddrUnix:
158                 if sa.Name != "" {
159                         addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
160                 }
161         }
162         return
163 }
164
165 // WriteToUnix writes a packet to addr via c, copying the payload from b.
166 //
167 // WriteToUnix can be made to time out and return an error with
168 // Timeout() == true after a fixed time limit; see SetDeadline and
169 // SetWriteDeadline.  On packet-oriented connections, write timeouts
170 // are rare.
171 func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err error) {
172         if !c.ok() {
173                 return 0, syscall.EINVAL
174         }
175         if addr.Net != sotypeToNet(c.fd.sotype) {
176                 return 0, syscall.EAFNOSUPPORT
177         }
178         sa := &syscall.SockaddrUnix{Name: addr.Name}
179         return c.fd.WriteTo(b, sa)
180 }
181
182 // WriteTo implements the PacketConn WriteTo method.
183 func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) {
184         if !c.ok() {
185                 return 0, syscall.EINVAL
186         }
187         a, ok := addr.(*UnixAddr)
188         if !ok {
189                 return 0, &OpError{"write", c.fd.net, addr, syscall.EINVAL}
190         }
191         return c.WriteToUnix(b, a)
192 }
193
194 // WriteMsgUnix writes a packet to addr via c, copying the payload
195 // from b and the associated out-of-band data from oob.  It returns
196 // the number of payload and out-of-band bytes written.
197 func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
198         if !c.ok() {
199                 return 0, 0, syscall.EINVAL
200         }
201         if addr != nil {
202                 if addr.Net != sotypeToNet(c.fd.sotype) {
203                         return 0, 0, syscall.EAFNOSUPPORT
204                 }
205                 sa := &syscall.SockaddrUnix{Name: addr.Name}
206                 return c.fd.WriteMsg(b, oob, sa)
207         }
208         return c.fd.WriteMsg(b, oob, nil)
209 }
210
211 // CloseRead shuts down the reading side of the Unix domain connection.
212 // Most callers should just use Close.
213 func (c *UnixConn) CloseRead() error {
214         if !c.ok() {
215                 return syscall.EINVAL
216         }
217         return c.fd.CloseRead()
218 }
219
220 // CloseWrite shuts down the writing side of the Unix domain connection.
221 // Most callers should just use Close.
222 func (c *UnixConn) CloseWrite() error {
223         if !c.ok() {
224                 return syscall.EINVAL
225         }
226         return c.fd.CloseWrite()
227 }
228
229 // DialUnix connects to the remote address raddr on the network net,
230 // which must be "unix", "unixgram" or "unixpacket".  If laddr is not
231 // nil, it is used as the local address for the connection.
232 func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
233         return dialUnix(net, laddr, raddr, noDeadline)
234 }
235
236 func dialUnix(net string, laddr, raddr *UnixAddr, deadline time.Time) (*UnixConn, error) {
237         switch net {
238         case "unix", "unixgram", "unixpacket":
239         default:
240                 return nil, UnknownNetworkError(net)
241         }
242         fd, err := unixSocket(net, laddr, raddr, "dial", deadline)
243         if err != nil {
244                 return nil, err
245         }
246         return newUnixConn(fd), nil
247 }
248
249 // UnixListener is a Unix domain socket listener.  Clients should
250 // typically use variables of type Listener instead of assuming Unix
251 // domain sockets.
252 type UnixListener struct {
253         fd   *netFD
254         path string
255 }
256
257 // ListenUnix announces on the Unix domain socket laddr and returns a
258 // Unix listener.  The network net must be "unix" or "unixpacket".
259 func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
260         switch net {
261         case "unix", "unixpacket":
262         default:
263                 return nil, UnknownNetworkError(net)
264         }
265         if laddr == nil {
266                 return nil, &OpError{"listen", net, nil, errMissingAddress}
267         }
268         fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
269         if err != nil {
270                 return nil, err
271         }
272         err = syscall.Listen(fd.sysfd, listenerBacklog)
273         if err != nil {
274                 fd.Close()
275                 return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
276         }
277         return &UnixListener{fd, laddr.Name}, nil
278 }
279
280 // AcceptUnix accepts the next incoming call and returns the new
281 // connection and the remote address.
282 func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
283         if l == nil || l.fd == nil {
284                 return nil, syscall.EINVAL
285         }
286         fd, err := l.fd.accept(sockaddrToUnix)
287         if err != nil {
288                 return nil, err
289         }
290         c := newUnixConn(fd)
291         return c, nil
292 }
293
294 // Accept implements the Accept method in the Listener interface; it
295 // waits for the next call and returns a generic Conn.
296 func (l *UnixListener) Accept() (c Conn, err error) {
297         c1, err := l.AcceptUnix()
298         if err != nil {
299                 return nil, err
300         }
301         return c1, nil
302 }
303
304 // Close stops listening on the Unix address.  Already accepted
305 // connections are not closed.
306 func (l *UnixListener) Close() error {
307         if l == nil || l.fd == nil {
308                 return syscall.EINVAL
309         }
310
311         // The operating system doesn't clean up
312         // the file that announcing created, so
313         // we have to clean it up ourselves.
314         // There's a race here--we can't know for
315         // sure whether someone else has come along
316         // and replaced our socket name already--
317         // but this sequence (remove then close)
318         // is at least compatible with the auto-remove
319         // sequence in ListenUnix.  It's only non-Go
320         // programs that can mess us up.
321         if l.path[0] != '@' {
322                 syscall.Unlink(l.path)
323         }
324         return l.fd.Close()
325 }
326
327 // Addr returns the listener's network address.
328 func (l *UnixListener) Addr() Addr { return l.fd.laddr }
329
330 // SetDeadline sets the deadline associated with the listener.
331 // A zero time value disables the deadline.
332 func (l *UnixListener) SetDeadline(t time.Time) (err error) {
333         if l == nil || l.fd == nil {
334                 return syscall.EINVAL
335         }
336         return setDeadline(l.fd, t)
337 }
338
339 // File returns a copy of the underlying os.File, set to blocking
340 // mode.  It is the caller's responsibility to close f when finished.
341 // Closing l does not affect f, and closing f does not affect l.
342 //
343 // The returned os.File's file descriptor is different from the
344 // connection's.  Attempting to change properties of the original
345 // using this duplicate may or may not have the desired effect.
346 func (l *UnixListener) File() (f *os.File, err error) { return l.fd.dup() }
347
348 // ListenUnixgram listens for incoming Unix datagram packets addressed
349 // to the local address laddr.  The network net must be "unixgram".
350 // The returned connection's ReadFrom and WriteTo methods can be used
351 // to receive and send packets with per-packet addressing.
352 func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
353         switch net {
354         case "unixgram":
355         default:
356                 return nil, UnknownNetworkError(net)
357         }
358         if laddr == nil {
359                 return nil, &OpError{"listen", net, nil, errMissingAddress}
360         }
361         fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
362         if err != nil {
363                 return nil, err
364         }
365         return newUnixConn(fd), nil
366 }