if err != nil {
return err
}
- return f.CloseAtomicallyReplace()
+ err = f.CloseAtomicallyReplace()
+ if err != nil {
+ return err
+ }
+ return syncPath(filepath.Dir(file.Path))
}
return err
}
- return f.CloseAtomicallyReplace()
+ err = f.CloseAtomicallyReplace()
+ if err != nil {
+ return err
+ }
+ return syncPath(filepath.Dir(dstPath))
}
import (
"bytes"
"fmt"
+ "os"
)
func alignBufferTo(b *bytes.Buffer, align int) {
b.WriteByte(0)
}
}
+
+// syncPath syncs path, which should be a directory. To guarantee durability
+// it must be called on a parent directory after adding, renaming or removing
+// files therein.
+//
+// Calling sync on the files itself is not enough according to POSIX; man 2
+// fsync: "Calling fsync() does not necessarily ensure that the entry in the
+// directory containing the file has also reached disk. For that an explicit
+// fsync() on a file descriptor for the directory is also needed."
+func syncPath(path string) error {
+ x, err := os.Open(path)
+ if err != nil {
+ return err
+ }
+ err = x.Sync()
+ closeErr := x.Close()
+ if err != nil {
+ return err
+ }
+ return closeErr
+}
if err != nil {
return err
}
- return f.CloseAtomicallyReplace()
+ err = f.CloseAtomicallyReplace()
+ if err != nil {
+ return err
+ }
+ return syncPath(filepath.Dir(path))
}