From 80d2db2e86dedf3e7f9a013ea5d84660267ee568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20Kerherv=C3=A9?= Date: Tue, 3 Feb 2015 16:27:39 -0800 Subject: [PATCH] Fix ignored last line of resolv.conf When ClientConfigFromFile is given a file that is missing a newline before EOF, then the last directive is completely ignored. This also adds a very basic test for a normal resolv.conf parsing. --- clientconfig.go | 9 +++++-- clientconfig_test.go | 61 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 clientconfig_test.go diff --git a/clientconfig.go b/clientconfig.go index 87cf8961..0681e491 100644 --- a/clientconfig.go +++ b/clientconfig.go @@ -26,14 +26,19 @@ func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) { } defer file.Close() c := new(ClientConfig) - b := bufio.NewReader(file) + scanner := bufio.NewScanner(file) c.Servers = make([]string, 0) c.Search = make([]string, 0) c.Port = "53" c.Ndots = 1 c.Timeout = 5 c.Attempts = 2 - for line, ok := b.ReadString('\n'); ok == nil; line, ok = b.ReadString('\n') { + + for scanner.Scan() { + if err := scanner.Err(); err != nil { + return nil, err + } + line := scanner.Text() f := strings.Fields(line) if len(f) < 1 { continue diff --git a/clientconfig_test.go b/clientconfig_test.go new file mode 100644 index 00000000..fa63657b --- /dev/null +++ b/clientconfig_test.go @@ -0,0 +1,61 @@ +package dns + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" +) + +const normal string = ` +# This file is automatically generated. +# +domain somedomain.com +nameserver 10.28.10.2 +nameserver 11.28.10.1 +` + +const missingNewline string = ` +# This file is automatically generated. +# +domain somedomain.com +nameserver 10.28.10.2 +nameserver 11.28.10.1` // <- NOTE: NO newline. + +func testConfig(t *testing.T, data string) { + tempDir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatalf("TempDir: %v", err) + } + defer os.RemoveAll(tempDir) + + path := filepath.Join(tempDir, "resolv.conf") + if err := ioutil.WriteFile(path, []byte(data), 0644); err != nil { + t.Fatalf("WriteFile: %v", err) + } + cc, err := ClientConfigFromFile(path) + if err != nil { + t.Errorf("error parsing resolv.conf: %s", err) + } + if l := len(cc.Servers); l != 2 { + t.Errorf("incorrect number of nameservers detected: %d", l) + } + if l := len(cc.Search); l != 1 { + t.Errorf("domain directive not parsed correctly: %v", cc.Search) + } else { + if cc.Search[0] != "somedomain.com" { + t.Errorf("domain is unexpected: %v", cc.Search[0]) + } + } +} + +// Test we can read a normally formed resolv.conf. +func TestNameserver(t *testing.T) { + testConfig(t, normal) +} + +// Don't drop the last line if there is no newline before EOF. +func TestMissingFinalNewLine(t *testing.T) { + testConfig(t, missingNewline) + +}