all: Convert folders to use filesystem abstraction
GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4228
This commit is contained in:
committed by
Jakob Borg
parent
ab8c2fb5c7
commit
3d8b4a42b7
@@ -8,10 +8,10 @@ package osutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -25,7 +25,8 @@ var (
|
||||
// returned on Close, so a lazy user can ignore errors until Close.
|
||||
type AtomicWriter struct {
|
||||
path string
|
||||
next *os.File
|
||||
next fs.File
|
||||
fs fs.Filesystem
|
||||
err error
|
||||
}
|
||||
|
||||
@@ -33,11 +34,19 @@ type AtomicWriter struct {
|
||||
// instead of the given name. The file is created with secure (0600)
|
||||
// permissions.
|
||||
func CreateAtomic(path string) (*AtomicWriter, error) {
|
||||
fs := fs.NewFilesystem(fs.FilesystemTypeBasic, filepath.Dir(path))
|
||||
return CreateAtomicFilesystem(fs, filepath.Base(path))
|
||||
}
|
||||
|
||||
// CreateAtomicFilesystem is like os.Create, except a temporary file name is used
|
||||
// instead of the given name. The file is created with secure (0600)
|
||||
// permissions.
|
||||
func CreateAtomicFilesystem(filesystem fs.Filesystem, path string) (*AtomicWriter, error) {
|
||||
// The security of this depends on the tempfile having secure
|
||||
// permissions, 0600, from the beginning. This is what ioutil.TempFile
|
||||
// does. We have a test that verifies that that is the case, should this
|
||||
// ever change in the standard library in the future.
|
||||
fd, err := ioutil.TempFile(filepath.Dir(path), TempPrefix)
|
||||
fd, err := TempFile(filesystem, filepath.Dir(path), TempPrefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -45,6 +54,7 @@ func CreateAtomic(path string) (*AtomicWriter, error) {
|
||||
w := &AtomicWriter{
|
||||
path: path,
|
||||
next: fd,
|
||||
fs: filesystem,
|
||||
}
|
||||
|
||||
return w, nil
|
||||
@@ -71,7 +81,7 @@ func (w *AtomicWriter) Close() error {
|
||||
}
|
||||
|
||||
// Try to not leave temp file around, but ignore error.
|
||||
defer os.Remove(w.next.Name())
|
||||
defer w.fs.Remove(w.next.Name())
|
||||
|
||||
if err := w.next.Sync(); err != nil {
|
||||
w.err = err
|
||||
@@ -88,17 +98,21 @@ func (w *AtomicWriter) Close() error {
|
||||
// either. Return this error because it may be more informative. On non-
|
||||
// Windows we want the atomic rename behavior so we don't attempt remove.
|
||||
if runtime.GOOS == "windows" {
|
||||
if err := os.Remove(w.path); err != nil && !os.IsNotExist(err) {
|
||||
if err := w.fs.Remove(w.path); err != nil && !fs.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.Rename(w.next.Name(), w.path); err != nil {
|
||||
if err := w.fs.Rename(w.next.Name(), w.path); err != nil {
|
||||
w.err = err
|
||||
return err
|
||||
}
|
||||
|
||||
SyncDir(filepath.Dir(w.next.Name()))
|
||||
// fsync the directory too
|
||||
if fd, err := w.fs.Open(filepath.Dir(w.next.Name())); err == nil {
|
||||
fd.Sync()
|
||||
fd.Close()
|
||||
}
|
||||
|
||||
// Set w.err to return appropriately for any future operations.
|
||||
w.err = ErrClosed
|
||||
|
||||
Reference in New Issue
Block a user