X-Git-Url: https://ruderich.org/simon/gitweb/?a=blobdiff_plain;f=file.go;h=1d102a4e09d0152547485da18c051d727d9510b2;hb=278c50be3d8a8c433aa862d602492112b9f26a67;hp=e06a9bce335ccc4e4444e5f8ea9502d27df09eba;hpb=44a325a9bea5f53c6489cecb3691709306a1814c;p=nsscash%2Fnsscash.git diff --git a/file.go b/file.go index e06a9bc..1d102a4 100644 --- a/file.go +++ b/file.go @@ -1,6 +1,6 @@ // Download and write files atomically to the file system -// Copyright (C) 2019 Simon Ruderich +// Copyright (C) 2019-2021 Simon Ruderich // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -30,6 +30,7 @@ import ( "syscall" "time" + "github.com/google/renameio" "github.com/pkg/errors" ) @@ -89,12 +90,17 @@ func fetchFile(file *File, state *State) error { t = zero // force download } + oldT := t status, body, err := fetchIfModified(file.Url, file.Username, file.Password, file.CA, &t) if err != nil { return err } if status == http.StatusNotModified { + if oldT.IsZero() { + return fmt.Errorf("status code 304 " + + "but did not send If-Modified-Since") + } log.Printf("%q -> %q: not modified", file.Url, file.Path) return nil } @@ -159,18 +165,11 @@ func deployFile(file *File) error { return fmt.Errorf("refusing to write empty file") } - // Write the file in an atomic fashion by creating a temporary file - // and renaming it over the target file - - dir := filepath.Dir(file.Path) - name := filepath.Base(file.Path) - - f, err := ioutil.TempFile(dir, "tmp-"+name+"-") + f, err := renameio.TempFile(filepath.Dir(file.Path), file.Path) if err != nil { return err } - defer os.Remove(f.Name()) - defer f.Close() + defer f.Cleanup() // Apply permissions/user/group from the target file but remove the // write permissions to discourage manual modifications, use Stat @@ -199,9 +198,5 @@ func deployFile(file *File) error { if err != nil { return err } - err = f.Sync() - if err != nil { - return err - } - return os.Rename(f.Name(), file.Path) + return f.CloseAtomicallyReplace() }