From 965cb7fd1c1097e1dc597b02530c1f38c06dbfe3 Mon Sep 17 00:00:00 2001 From: Raphael Badin Date: Mon, 15 May 2017 16:27:10 +0200 Subject: [PATCH] Write repo file using atomicfile This prevents clients from seeing half-written files because on POSIX systems renaming a file is an atomic operation. Drive-by: Add test for repo file permission. --- glide.lock | 2 ++ glide.yaml | 1 + pkg/repo/repo.go | 14 +++++++++++++- pkg/repo/repo_test.go | 10 +++++++++- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/glide.lock b/glide.lock index 624341837..d40407c3c 100644 --- a/glide.lock +++ b/glide.lock @@ -102,6 +102,8 @@ imports: version: ba18e35c5c1b36ef6334cad706eb681153d2d379 - name: github.com/exponent-io/jsonpath version: d6023ce2651d8eafb5c75bb0c7167536102ec9f5 +- name: github.com/facebookgo/atomicfile + version: 2de1f203e7d5e386a6833233882782932729f27e - name: github.com/facebookgo/symwalk version: 42004b9f322246749dd73ad71008b1f3160c0052 - name: github.com/ghodss/yaml diff --git a/glide.yaml b/glide.yaml index 0e4c3c3d0..334b153e2 100644 --- a/glide.yaml +++ b/glide.yaml @@ -41,6 +41,7 @@ import: - package: github.com/gobwas/glob version: ^0.2.1 - package: github.com/evanphx/json-patch +- package: github.com/facebookgo/atomicfile - package: github.com/facebookgo/symwalk - package: github.com/BurntSushi/toml version: ~0.3.0 diff --git a/pkg/repo/repo.go b/pkg/repo/repo.go index cbf54c572..5e1b5c6cd 100644 --- a/pkg/repo/repo.go +++ b/pkg/repo/repo.go @@ -23,6 +23,7 @@ import ( "os" "time" + "github.com/facebookgo/atomicfile" "github.com/ghodss/yaml" ) @@ -134,9 +135,20 @@ func (r *RepoFile) Remove(name string) bool { // WriteFile writes a repositories file to the given path. func (r *RepoFile) WriteFile(path string, perm os.FileMode) error { + f, err := atomicfile.New(path, perm) + if err != nil { + return err + } + data, err := yaml.Marshal(r) if err != nil { return err } - return ioutil.WriteFile(path, data, perm) + + _, err = f.File.Write(data) + if err != nil { + return err + } + + return f.Close() } diff --git a/pkg/repo/repo_test.go b/pkg/repo/repo_test.go index 6aee41faf..d4500c9e2 100644 --- a/pkg/repo/repo_test.go +++ b/pkg/repo/repo_test.go @@ -201,10 +201,18 @@ func TestWriteFile(t *testing.T) { t.Errorf("failed to create test-file (%v)", err) } defer os.Remove(repoFile.Name()) - if err := sampleRepository.WriteFile(repoFile.Name(), 744); err != nil { + + fileMode := os.FileMode(0744) + if err := sampleRepository.WriteFile(repoFile.Name(), fileMode); err != nil { t.Errorf("failed to write file (%v)", err) } + info, _ := os.Stat(repoFile.Name()) + mode := info.Mode() + if mode != fileMode { + t.Errorf("incorrect file mode: %s (expected %s)", mode, fileMode) + } + repos, err := LoadRepositoriesFile(repoFile.Name()) if err != nil { t.Errorf("failed to load file (%v)", err)