diff --git a/internal/fs/file.go b/internal/fs/file.go index b5cd5ef..d1b52ab 100644 --- a/internal/fs/file.go +++ b/internal/fs/file.go @@ -45,7 +45,7 @@ type File struct { name string info os.FileInfo - ioLock sync.Mutex + ioLock *sync.Mutex readOpReader *ioext.CounterReadCloser readOpWriter io.WriteCloser @@ -69,6 +69,7 @@ func NewFile( compressionLevel string, getFileBuffer func() (cache.WriteCache, func() error, error), + ioLock *sync.Mutex, name string, info os.FileInfo, @@ -88,6 +89,7 @@ func NewFile( compressionLevel: compressionLevel, getFileBuffer: getFileBuffer, + ioLock: ioLock, name: name, info: info, diff --git a/pkg/fs/filesystem.go b/pkg/fs/filesystem.go index 0052f9d..039c0d8 100644 --- a/pkg/fs/filesystem.go +++ b/pkg/fs/filesystem.go @@ -9,6 +9,7 @@ import ( "path" "path/filepath" "strconv" + "sync" "time" models "github.com/pojntfx/stfs/internal/db/sqlite/models/metadata" @@ -31,6 +32,8 @@ type STFS struct { getFileBuffer func() (cache.WriteCache, func() error, error) ignoreReadWritePermissions bool + ioLock sync.Mutex + onHeader func(hdr *models.Header) log *logging.JSONLogger } @@ -76,6 +79,9 @@ func (f *STFS) Create(name string) (afero.File, error) { "name": name, }) + f.ioLock.Lock() + defer f.ioLock.Unlock() + return os.OpenFile(name, os.O_CREATE, 0666) } @@ -162,6 +168,9 @@ func (f *STFS) MkdirRoot(name string, perm os.FileMode) error { "perm": perm, }) + f.ioLock.Lock() + defer f.ioLock.Unlock() + return f.mknode(true, name, perm, true) } @@ -171,6 +180,9 @@ func (f *STFS) Mkdir(name string, perm os.FileMode) error { "perm": perm, }) + f.ioLock.Lock() + defer f.ioLock.Unlock() + return f.mknode(true, name, perm, false) } @@ -180,6 +192,9 @@ func (f *STFS) MkdirAll(path string, perm os.FileMode) error { "perm": perm, }) + f.ioLock.Lock() + defer f.ioLock.Unlock() + parts := filepath.SplitList(path) currentPath := "" @@ -213,6 +228,9 @@ func (f *STFS) OpenFile(name string, flag int, perm os.FileMode) (afero.File, er "perm": perm, }) + f.ioLock.Lock() + defer f.ioLock.Unlock() + flags := &ifs.FileFlags{} if flag&os.O_RDONLY != 0 { flags.Read = true @@ -285,6 +303,7 @@ func (f *STFS) OpenFile(name string, flag int, perm os.FileMode) (afero.File, er f.compressionLevel, f.getFileBuffer, + &f.ioLock, path.Base(hdr.Name), ifs.NewFileInfoFromTarHeader(hdr, f.log), @@ -299,6 +318,9 @@ func (f *STFS) Remove(name string) error { "name": name, }) + f.ioLock.Lock() + defer f.ioLock.Unlock() + return f.writeOps.Delete(name) } @@ -307,6 +329,9 @@ func (f *STFS) RemoveAll(path string) error { "path": path, }) + f.ioLock.Lock() + defer f.ioLock.Unlock() + return f.writeOps.Delete(path) } @@ -316,6 +341,9 @@ func (f *STFS) Rename(oldname, newname string) error { "newname": newname, }) + f.ioLock.Lock() + defer f.ioLock.Unlock() + return f.writeOps.Move(oldname, newname) } @@ -324,6 +352,9 @@ func (f *STFS) Stat(name string) (os.FileInfo, error) { "name": name, }) + f.ioLock.Lock() + defer f.ioLock.Unlock() + hdr, err := inventory.Stat( f.metadata, @@ -374,6 +405,9 @@ func (f *STFS) Chmod(name string, mode os.FileMode) error { "name": mode, }) + f.ioLock.Lock() + defer f.ioLock.Unlock() + hdr, err := inventory.Stat( f.metadata, @@ -401,6 +435,9 @@ func (f *STFS) Chown(name string, uid, gid int) error { "gid": gid, }) + f.ioLock.Lock() + defer f.ioLock.Unlock() + hdr, err := inventory.Stat( f.metadata, @@ -429,6 +466,9 @@ func (f *STFS) Chtimes(name string, atime time.Time, mtime time.Time) error { "mtime": mtime, }) + f.ioLock.Lock() + defer f.ioLock.Unlock() + hdr, err := inventory.Stat( f.metadata, @@ -455,6 +495,9 @@ func (f *STFS) LstatIfPossible(name string) (os.FileInfo, bool, error) { "name": name, }) + f.ioLock.Lock() + defer f.ioLock.Unlock() + return nil, false, config.ErrNotImplemented } @@ -464,6 +507,9 @@ func (f *STFS) SymlinkIfPossible(oldname, newname string) error { "newname": newname, }) + f.ioLock.Lock() + defer f.ioLock.Unlock() + return config.ErrNotImplemented } @@ -472,5 +518,8 @@ func (f *STFS) ReadlinkIfPossible(name string) (string, error) { "name": name, }) + f.ioLock.Lock() + defer f.ioLock.Unlock() + return "", config.ErrNotImplemented }