github.com/mem/u-root@v2.0.1-0.20181004165302-9b18b4636a33+incompatible/cmds/ntpdate/ntpdate.go (about)

     1  // Copyright 2016-2017 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // simple ntpd daemon in Go.
     6  package main
     7  
     8  import (
     9  	"bufio"
    10  	"flag"
    11  	"fmt"
    12  	"log"
    13  	"os"
    14  	"strings"
    15  	"syscall"
    16  	"time"
    17  
    18  	"github.com/beevik/ntp"
    19  )
    20  
    21  var (
    22  	config  = flag.String("config", "/etc/ntp.conf", "NTP config file.")
    23  	verbose = flag.Bool("verbose", false, "Verbose output")
    24  	debug   = func(string, ...interface{}) {}
    25  )
    26  
    27  const (
    28  	fallback = "time.google.com"
    29  )
    30  
    31  func parseServers(r *bufio.Reader) []string {
    32  	var uri []string
    33  	var l string
    34  	var err error
    35  
    36  	debug("Reading config file")
    37  	for err == nil {
    38  		// This handles the case where the last line doesn't end in \n
    39  		l, err = r.ReadString('\n')
    40  		debug("%v", l)
    41  		if w := strings.Fields(l); len(w) > 1 && w[0] == "server" {
    42  			// We look only for the server lines, we ignore options like iburst
    43  			// TODO(ganshun): figure out what options we want to support.
    44  			uri = append(uri, w[1])
    45  		}
    46  	}
    47  
    48  	return uri
    49  }
    50  
    51  func getTime(servers []string) (t time.Time, err error) {
    52  	for _, s := range servers {
    53  		debug("Getting time from %v", s)
    54  		if t, err = ntp.Time(s); err == nil {
    55  			// Right now we return on the first valid time.
    56  			// We can implement better heuristics here.
    57  			debug("Got time %v", t)
    58  			return
    59  		}
    60  		debug("Error getting time: %v", err)
    61  	}
    62  
    63  	err = fmt.Errorf("unable to get any time from servers %v", servers)
    64  	return
    65  }
    66  
    67  func main() {
    68  	var servers []string
    69  	flag.Parse()
    70  	if *verbose {
    71  		debug = log.Printf
    72  	}
    73  
    74  	debug("Reading NTP servers from config file: %v", *config)
    75  	f, err := os.Open(*config)
    76  	if err == nil {
    77  		defer f.Close()
    78  		servers = parseServers(bufio.NewReader(f))
    79  		debug("Found %v servers", len(servers))
    80  	} else {
    81  		log.Printf("Unable to open config file: %v\nFalling back to : %v", err, fallback)
    82  		servers = []string{fallback}
    83  	}
    84  
    85  	t, err := getTime(servers)
    86  	if err != nil {
    87  		log.Fatalf("Unable to get time: %v", err)
    88  	}
    89  
    90  	tv := syscall.NsecToTimeval(t.UnixNano())
    91  	if err = syscall.Settimeofday(&tv); err != nil {
    92  		log.Fatalf("Unable to set system time: %v", err)
    93  	}
    94  }