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 }