github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/juju/sockets/sockets_nix.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Copyright 2014 Cloudbase Solutions SRL
     3  // Licensed under the AGPLv3, see LICENCE file for details.
     4  
     5  // +build !windows
     6  
     7  package sockets
     8  
     9  import (
    10  	"io/ioutil"
    11  	"net"
    12  	"net/rpc"
    13  	"os"
    14  	"path/filepath"
    15  	"strings"
    16  
    17  	"github.com/juju/errors"
    18  )
    19  
    20  func Dial(socketPath string) (*rpc.Client, error) {
    21  	return rpc.Dial("unix", socketPath)
    22  }
    23  
    24  func Listen(socketPath string) (net.Listener, error) {
    25  	// In case the unix socket is present, delete it.
    26  	if err := os.Remove(socketPath); err != nil {
    27  		logger.Tracef("ignoring error on removing %q: %v", socketPath, err)
    28  	}
    29  	// Listen directly to abstract domain sockets.
    30  	if strings.HasPrefix(socketPath, "@") {
    31  		listener, err := net.Listen("unix", socketPath)
    32  		return listener, errors.Trace(err)
    33  	}
    34  	// We first create the socket in a temporary directory as a subdirectory of
    35  	// the target dir so we know we can get the permissions correct and still
    36  	// rename the socket into the correct place.
    37  	// ioutil.TempDir creates the temporary directory as 0700 so it starts with
    38  	// the right perms as well.
    39  	socketDir := filepath.Dir(socketPath)
    40  	tempdir, err := ioutil.TempDir(socketDir, "")
    41  	if err != nil {
    42  		return nil, errors.Trace(err)
    43  	}
    44  	defer os.RemoveAll(tempdir)
    45  	// Keep the socket path as short as possible so as not to
    46  	// exceed the 108 length limit.
    47  	tempSocketPath := filepath.Join(tempdir, "s")
    48  	listener, err := net.Listen("unix", tempSocketPath)
    49  	if err != nil {
    50  		logger.Errorf("failed to listen on unix:%s: %v", tempSocketPath, err)
    51  		return nil, errors.Trace(err)
    52  	}
    53  	if err := os.Chmod(tempSocketPath, 0700); err != nil {
    54  		listener.Close()
    55  		return nil, errors.Annotatef(err, "could not chmod socket %v", tempSocketPath)
    56  	}
    57  	if err := os.Rename(tempSocketPath, socketPath); err != nil {
    58  		listener.Close()
    59  		return nil, errors.Annotatef(err, "could not rename socket %v", tempSocketPath)
    60  	}
    61  	return listener, nil
    62  }