ntp: set real-time clock (hwclock) if present
This commit is contained in:
parent
238bbfa55e
commit
6c059494af
@ -4,29 +4,50 @@ package main
|
||||
import (
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/beevik/ntp"
|
||||
)
|
||||
|
||||
func set() error {
|
||||
func set(rtc *os.File) error {
|
||||
r, err := ntp.Query("0.gokrazy.pool.ntp.org")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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() {
|
||||
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 {
|
||||
if err := set(); err != nil {
|
||||
if err := set(rtc); err != nil {
|
||||
log.Fatalf("setting time failed: %v", err)
|
||||
}
|
||||
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
|
||||
// privileges, but retaining the CAP_SYS_TIME capability to change the system
|
||||
// clock.
|
||||
func mustDropPrivileges() {
|
||||
func mustDropPrivileges(rtc *os.File) {
|
||||
if os.Getenv("NTP_PRIVILEGES_DROPPED") == "1" {
|
||||
return
|
||||
}
|
||||
@ -71,6 +71,10 @@ func mustDropPrivileges() {
|
||||
|
||||
cmd := exec.Command(os.Args[0])
|
||||
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.Stderr = os.Stderr
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
package main
|
||||
|
||||
import "os"
|
||||
|
||||
// mustDropPrivileges (on Go < 1.9) does nothing, as the AmbientCaps field in
|
||||
// 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