summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2017-01-18 22:24:27 -0500
committerLuke Shumaker <lukeshu@sbcglobal.net>2017-01-18 22:24:27 -0500
commit58861a7cbcd8f745ec0cc99e7dced13da07eff68 (patch)
treeb83769fe0fe6b72d13a6de2c7b833d6946fe63ca
initial commit
-rw-r--r--.gitignore2
-rw-r--r--Makefile24
-rw-r--r--systemd-timesyncd-wait.go29
-rw-r--r--systemd-timesyncd-wait.service11
-rw-r--r--systemd-timesyncd-wait.socket7
-rw-r--r--systemd-timesyncd-wrap.go98
-rw-r--r--systemd-timesyncd.service.d-wait.conf7
7 files changed, 178 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f2c3279
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/systemd-timesyncd-wait
+/systemd-timesyncd-wrap
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..282ed1a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,24 @@
+files.out.all += systemd-timesyncd-wait systemd-timesyncd-wrap
+files.sys.all += /usr/lib/systemd/systemd-timesyncd-wait
+files.sys.all += /usr/lib/systemd/systemd-timesyncd-wrap
+files.sys.all += /usr/lib/systemd/system/systemd-timesyncd-wait.socket
+files.sys.all += /usr/lib/systemd/system/systemd-timesyncd-wait.service
+files.sys.all += /usr/lib/systemd/system/systemd-timesyncd.service.d/wait.conf
+
+outdir = .
+srcdir = .
+all: $(addprefix $(outdir)/,$(files.out.all))
+clean:
+ rm -f -- $(addprefix $(outdir)/,$(files.out.all))
+install: $(addprefix $(DESTDIR),$(files.sys.all))
+.PHONY: all clean install
+
+$(outdir)/%: $(srcdir)/%.go
+ go build -o $@ $<
+
+$(DESTDIR)/usr/lib/systemd/%: $(outdir)/%
+ install -DTm755 $< $@
+$(DESTDIR)/usr/lib/systemd/system/%: $(srcdir)/%
+ install -DTm644 $< $@
+$(DESTDIR)/usr/lib/systemd/system/systemd-timesyncd.service.d/wait.conf: systemd-timesyncd.service.d-wait.conf
+ install -DTm644 $< $@
diff --git a/systemd-timesyncd-wait.go b/systemd-timesyncd-wait.go
new file mode 100644
index 0000000..9275502
--- /dev/null
+++ b/systemd-timesyncd-wait.go
@@ -0,0 +1,29 @@
+package main
+
+import (
+ "net"
+ "os"
+)
+
+func main() {
+ sync_sockname := "/run/timesyncd/time-sync.sock"
+
+ sync_sock, err := net.ListenUnixgram("unixgram", &net.UnixAddr{Net: "unixgram", Name: sync_sockname})
+ if err != nil {
+ os.Stderr.WriteString(err.Error())
+ os.Stderr.Write([]byte{'\n'})
+ os.Exit(127)
+ }
+
+ var dat [4096]byte
+ n, err := sync_sock.Read(dat[:])
+ if err != nil {
+ os.Stderr.WriteString(err.Error())
+ os.Stderr.Write([]byte{'\n'})
+ os.Exit(127)
+ }
+ if string(dat[:n]) != "READY=1" {
+ os.Exit(127)
+ }
+ os.Exit(0)
+}
diff --git a/systemd-timesyncd-wait.service b/systemd-timesyncd-wait.service
new file mode 100644
index 0000000..3237130
--- /dev/null
+++ b/systemd-timesyncd-wait.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Network Time Synchronized
+DefaultDependencies=no
+After=systemd-timesyncd-wait.socket
+Before=time-sync.target
+Wants=time-sync.target systemd-timesyncd-wait.socket
+
+[Service]
+Type=oneshot
+ExecStart=/usr/lib/systemd/systemd-timesyncd-wait
+TimeoutStartSec=infinity
diff --git a/systemd-timesyncd-wait.socket b/systemd-timesyncd-wait.socket
new file mode 100644
index 0000000..3112218
--- /dev/null
+++ b/systemd-timesyncd-wait.socket
@@ -0,0 +1,7 @@
+[Unit]
+Description=Network Time Synchronized Socket
+DefaultDependencies=no
+After=systemd-remount-fs.service systemd-tmpfiles-setup.service
+
+[Socket]
+ListenDatagram=/run/timesyncd/time-sync.sock
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())
+ }
+}
diff --git a/systemd-timesyncd.service.d-wait.conf b/systemd-timesyncd.service.d-wait.conf
new file mode 100644
index 0000000..8342e53
--- /dev/null
+++ b/systemd-timesyncd.service.d-wait.conf
@@ -0,0 +1,7 @@
+[Unit]
+Wants=systemd-timesyncd-wait.socket
+After=systemd-timesyncd-wait.socket
+
+[Service]
+Sockets=
+ExecStart=/usr/lib/systemd/systemd-timesyncd-wrap /usr/lib/systemd/systemd-timesyncd