2018-08-27 22:21:45 +02:00
|
|
|
package nethelpers
|
2017-09-17 23:41:51 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"net"
|
2018-08-27 15:22:32 +02:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2019-03-22 19:41:12 +01:00
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
2017-09-17 23:41:51 +02:00
|
|
|
)
|
|
|
|
|
2018-02-17 14:12:44 +01:00
|
|
|
func PreparePrivateSockpath(sockpath string) error {
|
|
|
|
sockdir := filepath.Dir(sockpath)
|
2017-09-17 23:41:51 +02:00
|
|
|
sdstat, err := os.Stat(sockdir)
|
|
|
|
if err != nil {
|
2018-02-17 14:12:44 +01:00
|
|
|
return errors.Wrapf(err, "cannot stat(2) '%s'", sockdir)
|
2017-09-17 23:41:51 +02:00
|
|
|
}
|
|
|
|
if !sdstat.IsDir() {
|
2018-02-17 14:12:44 +01:00
|
|
|
return errors.Errorf("not a directory: %s", sockdir)
|
2017-09-17 23:41:51 +02:00
|
|
|
}
|
|
|
|
p := sdstat.Mode().Perm()
|
|
|
|
if p&0007 != 0 {
|
2018-02-17 14:12:44 +01:00
|
|
|
return errors.Errorf("socket directory must not be world-accessible: %s (permissions are %#o)", sockdir, p)
|
2017-09-17 23:41:51 +02:00
|
|
|
}
|
|
|
|
|
2017-09-18 00:16:10 +02:00
|
|
|
// Maybe things have not been cleaned up before
|
2018-02-17 14:12:44 +01:00
|
|
|
s, err := os.Stat(sockpath)
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "cannot stat(2) '%s'", sockpath)
|
|
|
|
}
|
|
|
|
if s.Mode()&os.ModeSocket == 0 {
|
|
|
|
return errors.Errorf("unexpected file type at path '%s'", sockpath)
|
|
|
|
}
|
|
|
|
err = os.Remove(sockpath)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "cannot remove presumably stale socket '%s'", sockpath)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func ListenUnixPrivate(sockaddr *net.UnixAddr) (*net.UnixListener, error) {
|
|
|
|
|
|
|
|
if err := PreparePrivateSockpath(sockaddr.Name); err != nil {
|
|
|
|
return nil, err
|
2017-09-18 00:16:10 +02:00
|
|
|
}
|
|
|
|
|
2017-09-17 23:41:51 +02:00
|
|
|
return net.ListenUnix("unix", sockaddr)
|
|
|
|
}
|