github.com/nycdavid/zeus@v0.0.0-20201208104106-9ba439429e03/go/unixsocket/unixsocket.go (about)

     1  // package unixsocket implements type Usock which supports out-of-band transfer
     2  // of open files. The API is {Read,Write}{FD,Message}. Messages are buffered in
     3  // both directions.
     4  //
     5  // When ReadFD is called, it will interpret the first queued OOB datum already
     6  // received, if any. Otherwise it will attempt to receive OOB data from the next
     7  // packet. The packet will be assumed to be a UnixRights message, granting
     8  // access to an open file from another process, and will be decoded as such.
     9  //
    10  // ReadFD will not always block if called in a scenario where there is pending
    11  // data but no OOB data in the first pending packet. This situation is undefined
    12  // (realistically, currently un-thought-about, as zeus has a very regular
    13  // protocol that obviates this concern).
    14  package unixsocket
    15  
    16  import (
    17  	"io/ioutil"
    18  	"log"
    19  	"os"
    20  	"path"
    21  	"path/filepath"
    22  	"syscall"
    23  )
    24  
    25  func Socketpair(typ int) (a, b *os.File, err error) {
    26  	fd, err := syscall.Socketpair(syscall.AF_UNIX, typ, 0)
    27  	if err != nil {
    28  		e := os.NewSyscallError("socketpair", err.(syscall.Errno))
    29  		return nil, nil, e
    30  	}
    31  
    32  	a = os.NewFile(uintptr(fd[0]), "socketpair-a")
    33  	b = os.NewFile(uintptr(fd[1]), "socketpair-b")
    34  	return
    35  }
    36  
    37  var sockName string
    38  
    39  func containsFile(pattern string, files []os.FileInfo) bool {
    40  	for _, f := range files {
    41  		matched, err := filepath.Match(pattern, f.Name())
    42  		if err != nil {
    43  			log.Fatal(err)
    44  		}
    45  		if matched {
    46  			return true
    47  		}
    48  	}
    49  	return false
    50  }
    51  
    52  func isProjectRoot(p string) bool {
    53  	files, err := ioutil.ReadDir(p)
    54  	if err != nil {
    55  		log.Fatal(err)
    56  	}
    57  	return containsFile("*Gemfile", files)
    58  }
    59  
    60  func projectRoot() string {
    61  	projectRootPath, err := os.Getwd()
    62  	if err != nil {
    63  		log.Fatal(err)
    64  	}
    65  
    66  	for isProjectRoot(projectRootPath) != true {
    67  		projectRootPath, err = filepath.Abs(path.Join(projectRootPath, ".."))
    68  		if projectRootPath == "/" || err != nil {
    69  			break
    70  		}
    71  	}
    72  	return projectRootPath
    73  }
    74  
    75  func init() {
    76  	sockName = os.Getenv("ZEUSSOCK")
    77  	if sockName == "" {
    78  		os.Chdir(projectRoot())
    79  		sockName = ".zeus.sock"
    80  	}
    81  }
    82  
    83  // SetZeusSockName sets the socket name used for zeus clients.
    84  // It is primarily exposed for testing purpose and is not safe to
    85  // modify after Zeus has started.
    86  func SetZeusSockName(n string) {
    87  	sockName = n
    88  }
    89  
    90  func ZeusSockName() string {
    91  	return sockName
    92  }