})
// update filter file
- // TODO(gri) should write a tmp file and atomically rename
- err := ioutil.WriteFile(*filter, buf.Bytes(), 0666)
- if err != nil {
- log.Stderrf("ioutil.Writefile(%s): %s", *filter, err)
+ if err := writeFileAtomically(*filter, buf.Bytes()); err != nil {
+ log.Stderrf("writeFileAtomically(%s): %s", *filter, err)
filterDelay.backoff(24 * 60) // back off exponentially, but try at least once a day
} else {
filterDelay.set(*filterMin) // revert to regular filter update schedule
package main
import (
+ "io"
+ "io/ioutil"
"os"
pathutil "path"
"sort"
return list[0:i]
}
+
+
+// writeFileAtomically writes data to a temporary file and then
+// atomically renames that file to the file named by filename.
+//
+func writeFileAtomically(filename string, data []byte) os.Error {
+ f, err := ioutil.TempFile(cwd, filename)
+ if err != nil {
+ return err
+ }
+ n, err := f.Write(data)
+ f.Close()
+ if err != nil {
+ return err
+ }
+ if n < len(data) {
+ return io.ErrShortWrite
+ }
+ return os.Rename(f.Name(), filename)
+}