ntp: set real-time clock (hwclock) if present
This commit is contained in:
parent
238bbfa55e
commit
6c059494af
@ -4,29 +4,50 @@ package main
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/beevik/ntp"
|
"github.com/beevik/ntp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func set() error {
|
func set(rtc *os.File) error {
|
||||||
r, err := ntp.Query("0.gokrazy.pool.ntp.org")
|
r, err := ntp.Query("0.gokrazy.pool.ntp.org")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
tv := syscall.NsecToTimeval(r.Time.UnixNano())
|
tv := syscall.NsecToTimeval(r.Time.UnixNano())
|
||||||
return syscall.Settimeofday(&tv)
|
if err := syscall.Settimeofday(&tv); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if rtc == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return setRTC(rtc, r.Time.UTC())
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||||
|
|
||||||
mustDropPrivileges()
|
var rtc *os.File
|
||||||
|
var err error
|
||||||
|
if os.Getenv("NTP_PRIVILEGES_DROPPED") == "1" {
|
||||||
|
if os.Getenv("NTP_RTC") == "1" {
|
||||||
|
rtc = os.NewFile(3, "/dev/rtc0")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rtc, err = os.Open("/dev/rtc0")
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mustDropPrivileges(rtc)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if err := set(); err != nil {
|
if err := set(rtc); err != nil {
|
||||||
log.Fatalf("setting time failed: %v", err)
|
log.Fatalf("setting time failed: %v", err)
|
||||||
}
|
}
|
||||||
time.Sleep(1*time.Hour + time.Duration(rand.Int63n(250))*time.Millisecond)
|
time.Sleep(1*time.Hour + time.Duration(rand.Int63n(250))*time.Millisecond)
|
||||||
|
@ -46,7 +46,7 @@ func getCaps() (caps, error) {
|
|||||||
// mustDropPrivileges executes the program in a child process, dropping root
|
// mustDropPrivileges executes the program in a child process, dropping root
|
||||||
// privileges, but retaining the CAP_SYS_TIME capability to change the system
|
// privileges, but retaining the CAP_SYS_TIME capability to change the system
|
||||||
// clock.
|
// clock.
|
||||||
func mustDropPrivileges() {
|
func mustDropPrivileges(rtc *os.File) {
|
||||||
if os.Getenv("NTP_PRIVILEGES_DROPPED") == "1" {
|
if os.Getenv("NTP_PRIVILEGES_DROPPED") == "1" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -71,6 +71,10 @@ func mustDropPrivileges() {
|
|||||||
|
|
||||||
cmd := exec.Command(os.Args[0])
|
cmd := exec.Command(os.Args[0])
|
||||||
cmd.Env = append(os.Environ(), "NTP_PRIVILEGES_DROPPED=1")
|
cmd.Env = append(os.Environ(), "NTP_PRIVILEGES_DROPPED=1")
|
||||||
|
if rtc != nil {
|
||||||
|
cmd.Env = append(cmd.Env, "NTP_RTC=1")
|
||||||
|
cmd.ExtraFiles = []*os.File{rtc}
|
||||||
|
}
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
// mustDropPrivileges (on Go < 1.9) does nothing, as the AmbientCaps field in
|
// mustDropPrivileges (on Go < 1.9) does nothing, as the AmbientCaps field in
|
||||||
// syscall.SysProcAttr was only introduced in Go 1.9.
|
// syscall.SysProcAttr was only introduced in Go 1.9.
|
||||||
func mustDropPrivileges() {
|
func mustDropPrivileges(*os.File) {
|
||||||
}
|
}
|
||||||
|
26
cmd/ntp/rtc.go
Normal file
26
cmd/ntp/rtc.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setRTC(rtc *os.File, now time.Time) error {
|
||||||
|
c := unix.RTCTime{
|
||||||
|
Sec: int32(now.Second()),
|
||||||
|
Min: int32(now.Minute()),
|
||||||
|
Hour: int32(now.Hour()),
|
||||||
|
Mday: int32(now.Day()),
|
||||||
|
Mon: int32(now.Month() - 1),
|
||||||
|
Year: int32(now.Year() - 1900),
|
||||||
|
}
|
||||||
|
if _, _, errno := unix.Syscall(unix.SYS_IOCTL, rtc.Fd(), unix.RTC_SET_TIME, uintptr(unsafe.Pointer(&c))); errno != 0 {
|
||||||
|
return errno
|
||||||
|
}
|
||||||
|
log.Printf("RTC set to %+v", c)
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user