summaryrefslogtreecommitdiff
path: root/systemd-timesyncd-wrap.go
diff options
context:
space:
mode:
Diffstat (limited to 'systemd-timesyncd-wrap.go')
-rw-r--r--systemd-timesyncd-wrap.go98
1 files changed, 98 insertions, 0 deletions
diff --git a/systemd-timesyncd-wrap.go b/systemd-timesyncd-wrap.go
new file mode 100644
index 0000000..3d5971b
--- /dev/null
+++ b/systemd-timesyncd-wrap.go
@@ -0,0 +1,98 @@
+package main
+
+import (
+ "net"
+ "os"
+ "strings"
+ "sync"
+ "syscall"
+)
+
+func socketUnixgram(name string) (*net.UnixConn, error) {
+ fd, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0)
+ if err != nil {
+ return nil, err
+ }
+ conn, err := net.FileConn(os.NewFile(uintptr(fd), name))
+ if err != nil {
+ return nil, err
+ }
+ unixConn := conn.(*net.UnixConn)
+ return unixConn, nil
+}
+
+func sendmsg(dat, oob []byte, sockname string) error {
+ writer, err := socketUnixgram(sockname)
+ if err != nil {
+ return err
+ }
+ _, _, err = writer.WriteMsgUnix(dat, oob, &net.UnixAddr{Net: "unixgram", Name: sockname})
+ return err
+}
+
+func main() {
+ sync_sockname := "/run/timesyncd/time-sync.sock"
+ fake_sockname := "/run/timesyncd/notify.sock"
+ real_sockname := os.Getenv("NOTIFY_SOCKET")
+
+ fake_sock, err := net.ListenUnixgram("unixgram", &net.UnixAddr{Net: "unixgram", Name: fake_sockname})
+ if err != nil {
+ os.Stderr.WriteString(err.Error())
+ os.Stderr.Write([]byte{'\n'})
+ os.Exit(127)
+ }
+
+ os.Setenv("NOTIFY_SOCKET", fake_sockname)
+ proc, err := os.StartProcess(os.Args[1], os.Args[1:], &os.ProcAttr{})
+ if err != nil {
+ os.Stderr.WriteString(err.Error())
+ os.Stderr.Write([]byte{'\n'})
+ os.Exit(127)
+ }
+
+ var wg sync.WaitGroup
+ wg.Add(1)
+ go func() {
+ synced := false
+ var dat [4096]byte
+ oob := make([]byte, syscall.CmsgSpace(syscall.SizeofUcred)+syscall.CmsgSpace(8*768))
+ for {
+ n, oobn, flags, _, err := fake_sock.ReadMsgUnix(dat[:], oob[:])
+ if err != nil {
+ break
+ }
+ if flags&syscall.MSG_TRUNC != 0 {
+ continue
+ }
+ if !synced {
+ for _, line := range strings.Split(string(dat[:n]), "\n") {
+ if strings.HasPrefix(line, "STATUS=Synchronized") {
+ _ = sendmsg([]byte(line), nil, sync_sockname)
+ synced = true
+ break
+ }
+ }
+ }
+ _ = sendmsg(dat[:n], oob[:oobn], real_sockname)
+ }
+ wg.Done()
+ }()
+
+ state, err := proc.Wait()
+ _ = fake_sock.Close()
+ wg.Wait()
+
+ if err != nil {
+ os.Stderr.WriteString(err.Error())
+ os.Stderr.Write([]byte{'\n'})
+ os.Exit(127)
+ }
+ status := state.Sys().(syscall.WaitStatus)
+ if status.Exited() {
+ os.Exit(status.ExitStatus())
+ }
+ if status.Signaled() {
+ self, _ := os.FindProcess(os.Getpid())
+ self.Signal(status.Signal())
+ }
+}