github.com/puellanivis/breton@v0.2.16/lib/files/socketfiles/unixsock.go (about)

     1  package socketfiles
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"net"
     7  	"net/url"
     8  	"os"
     9  
    10  	"github.com/puellanivis/breton/lib/files"
    11  )
    12  
    13  type unixHandler struct{}
    14  
    15  func init() {
    16  	files.RegisterScheme(&unixHandler{}, "unix", "unixgram")
    17  }
    18  
    19  func (h *unixHandler) Open(ctx context.Context, uri *url.URL) (files.Reader, error) {
    20  	path := uri.Path
    21  	if path == "" {
    22  		path = uri.Opaque
    23  	}
    24  	network := uri.Scheme
    25  
    26  	laddr, err := net.ResolveUnixAddr(network, path)
    27  	if err != nil {
    28  		return nil, files.PathError("open", uri.String(), err)
    29  	}
    30  
    31  	switch laddr.Network() {
    32  	case "unixgram":
    33  		conn, err := net.ListenUnixgram(network, laddr)
    34  		if err != nil {
    35  			return nil, files.PathError("open", uri.String(), err)
    36  		}
    37  
    38  		sock, err := sockReader(conn, uri.Query())
    39  		if err != nil {
    40  			conn.Close()
    41  			return nil, files.PathError("open", uri.String(), err)
    42  		}
    43  
    44  		return newDatagramReader(ctx, sock), nil
    45  
    46  	case "unix":
    47  		l, err := net.ListenUnix(network, laddr)
    48  		if err != nil {
    49  			return nil, files.PathError("open", uri.String(), err)
    50  		}
    51  
    52  		return newStreamReader(ctx, l)
    53  	}
    54  
    55  	return nil, files.PathError("create", uri.String(), errors.New("unknown unix socket type"))
    56  }
    57  
    58  func (h *unixHandler) Create(ctx context.Context, uri *url.URL) (files.Writer, error) {
    59  	path := uri.Path
    60  	if path == "" {
    61  		path = uri.Opaque
    62  	}
    63  	network := uri.Scheme
    64  
    65  	raddr, err := net.ResolveUnixAddr(network, path)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	q := uri.Query()
    71  
    72  	var laddr *net.UnixAddr
    73  
    74  	addr := q.Get(FieldLocalAddress)
    75  	if addr != "" {
    76  		laddr, err = net.ResolveUnixAddr(network, addr)
    77  		if err != nil {
    78  			return nil, files.PathError("create", uri.String(), err)
    79  		}
    80  	}
    81  
    82  	var conn *net.UnixConn
    83  	dial := func() error {
    84  		var err error
    85  
    86  		conn, err = net.DialUnix(network, laddr, raddr)
    87  
    88  		return err
    89  	}
    90  
    91  	if err := do(ctx, dial); err != nil {
    92  		return nil, files.PathError("create", uri.String(), err)
    93  	}
    94  
    95  	sock, err := sockWriter(conn, laddr != nil, q)
    96  	if err != nil {
    97  		conn.Close()
    98  		return nil, files.PathError("create", uri.String(), err)
    99  	}
   100  
   101  	switch network {
   102  	case "unix":
   103  		return newStreamWriter(ctx, sock), nil
   104  
   105  	case "unixgram", "unixpacket":
   106  		return newDatagramWriter(ctx, sock), nil
   107  	}
   108  
   109  	conn.Close()
   110  	return nil, files.PathError("create", uri.String(), errors.New("unknown unix socket type"))
   111  }
   112  
   113  func (h *unixHandler) List(ctx context.Context, uri *url.URL) ([]os.FileInfo, error) {
   114  	return nil, files.PathError("readdir", uri.String(), os.ErrInvalid)
   115  }