== REQUIREMENTS
 
 - Go, for `nsscash`
-  * github.com/pkg/errors
   * github.com/BurntSushi/toml
+  * github.com/google/renameio
+  * github.com/pkg/errors
 - C compiler, for `libnss_cash.so.2`
 
 - HTTP(S) server to provide the passwd/group/etc. files
 
        "syscall"
        "time"
 
+       "github.com/google/renameio"
        "github.com/pkg/errors"
 )
 
                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
        if err != nil {
                return err
        }
-       err = f.Sync()
-       if err != nil {
-               return err
-       }
-       return os.Rename(f.Name(), file.Path)
+       return f.CloseAtomicallyReplace()
 }
 
 
 require (
        github.com/BurntSushi/toml v0.3.1
+       github.com/google/renameio v0.1.1-0.20200217212219-353f81969824
        github.com/pkg/errors v0.8.1
 )
 
 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/google/renameio v0.1.1-0.20200217212219-353f81969824 h1:9q700G0beHecUuiZOuKgNqNsGQixTeDLnzVZ5nsW3lc=
+github.com/google/renameio v0.1.1-0.20200217212219-353f81969824/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
 github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 
        "log"
        "os"
        "path/filepath"
+
+       "github.com/google/renameio"
 )
 
 func main() {
                return fmt.Errorf("unsupported file type %v", t)
        }
 
-       dstDir := filepath.Dir(dstPath)
-       dstName := filepath.Base(dstPath)
-
        // We must create the file first or deployFile() will abort; this is
        // ugly because deployFile() already performs an atomic replacement
        // but the simplest solution with the least duplicate code
-       f, err := ioutil.TempFile(dstDir, "tmp-"+dstName+"-")
+       f, err := renameio.TempFile(filepath.Dir(dstPath), dstPath)
        if err != nil {
                return err
        }
-       tmpPath := f.Name()
-       defer os.Remove(tmpPath)
-       f.Close()
+       defer f.Cleanup()
 
        err = deployFile(&File{
                Type: t,
                Url:  srcPath,
-               Path: tmpPath,
+               Path: f.Name(),
                body: x.Bytes(),
        })
        if err != nil {
                return err
        }
 
-       return os.Rename(tmpPath, dstPath)
+       return f.CloseAtomicallyReplace()
 }
 
        "os"
        "path/filepath"
        "time"
+
+       "github.com/google/renameio"
 )
 
 type State struct {
                return err
        }
 
-       // Write the file in an atomic fashion by creating a temporary file
-       // and renaming it over the target file
-
-       dir := filepath.Dir(path)
-       name := filepath.Base(path)
-
-       f, err := ioutil.TempFile(dir, "tmp-"+name+"-")
+       f, err := renameio.TempFile(filepath.Dir(path), path)
        if err != nil {
                return err
        }
-       defer os.Remove(f.Name())
-       defer f.Close()
+       defer f.Cleanup()
 
        _, err = f.Write(x)
        if err != nil {
                return err
        }
-       err = f.Sync()
-       if err != nil {
-               return err
-       }
-       return os.Rename(f.Name(), path)
+       return f.CloseAtomicallyReplace()
 }