mirror of
https://github.com/octoleo/syncthing.git
synced 2025-01-22 22:58:25 +00:00
lib/model: Cleanup redundant filesystem variables in folders (#7237)
This commit is contained in:
parent
5440d1dc3b
commit
a05dc6cc47
@ -45,6 +45,7 @@ type folder struct {
|
||||
shortID protocol.ShortID
|
||||
fset *db.FileSet
|
||||
ignores *ignore.Matcher
|
||||
mtimefs fs.Filesystem
|
||||
modTimeWindow time.Duration
|
||||
ctx context.Context // used internally, only accessible on serve lifetime
|
||||
done chan struct{} // used externally, accessible regardless of serve
|
||||
@ -100,6 +101,7 @@ func newFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg conf
|
||||
shortID: model.shortID,
|
||||
fset: fset,
|
||||
ignores: ignores,
|
||||
mtimefs: fset.MtimeFS(),
|
||||
modTimeWindow: cfg.ModTimeWindow(),
|
||||
done: make(chan struct{}),
|
||||
|
||||
@ -457,7 +459,6 @@ func (f *folder) scanSubdirs(subDirs []string) error {
|
||||
// to be cancelled.
|
||||
scanCtx, scanCancel := context.WithCancel(f.ctx)
|
||||
defer scanCancel()
|
||||
mtimefs := f.fset.MtimeFS()
|
||||
|
||||
scanConfig := scanner.Config{
|
||||
Folder: f.ID,
|
||||
@ -465,7 +466,7 @@ func (f *folder) scanSubdirs(subDirs []string) error {
|
||||
Matcher: f.ignores,
|
||||
TempLifetime: time.Duration(f.model.cfg.Options().KeepTemporariesH) * time.Hour,
|
||||
CurrentFiler: cFiler{snap},
|
||||
Filesystem: mtimefs,
|
||||
Filesystem: f.mtimefs,
|
||||
IgnorePerms: f.IgnorePerms,
|
||||
AutoNormalize: f.AutoNormalize,
|
||||
Hashers: f.model.numHashers(f.ID),
|
||||
@ -530,8 +531,8 @@ func (f *folder) scanSubdirs(subDirs []string) error {
|
||||
// We don't track it, but check if anything still exists
|
||||
// within and delete it otherwise.
|
||||
if fi.IsDirectory() && protocol.IsEncryptedParent(fi.Name) {
|
||||
if names, err := mtimefs.DirNames(fi.Name); err == nil && len(names) == 0 {
|
||||
mtimefs.Remove(fi.Name)
|
||||
if names, err := f.mtimefs.DirNames(fi.Name); err == nil && len(names) == 0 {
|
||||
f.mtimefs.Remove(fi.Name)
|
||||
}
|
||||
changes--
|
||||
return
|
||||
@ -570,7 +571,7 @@ func (f *folder) scanSubdirs(subDirs []string) error {
|
||||
switch f.Type {
|
||||
case config.FolderTypeReceiveOnly, config.FolderTypeReceiveEncrypted:
|
||||
default:
|
||||
if nf, ok := f.findRename(snap, mtimefs, res.File, alreadyUsed); ok {
|
||||
if nf, ok := f.findRename(snap, res.File, alreadyUsed); ok {
|
||||
batchAppend(nf, snap)
|
||||
changes++
|
||||
}
|
||||
@ -658,7 +659,7 @@ func (f *folder) scanSubdirs(subDirs []string) error {
|
||||
// it's still here. Simply stat:ing it wont do as there are
|
||||
// tons of corner cases (e.g. parent dir->symlink, missing
|
||||
// permissions)
|
||||
if !osutil.IsDeleted(mtimefs, file.Name) {
|
||||
if !osutil.IsDeleted(f.mtimefs, file.Name) {
|
||||
if ignoredParent != "" {
|
||||
// Don't ignore parents of this not ignored item
|
||||
toIgnore = toIgnore[:0]
|
||||
@ -727,7 +728,7 @@ func (f *folder) scanSubdirs(subDirs []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *folder) findRename(snap *db.Snapshot, mtimefs fs.Filesystem, file protocol.FileInfo, alreadyUsed map[string]struct{}) (protocol.FileInfo, bool) {
|
||||
func (f *folder) findRename(snap *db.Snapshot, file protocol.FileInfo, alreadyUsed map[string]struct{}) (protocol.FileInfo, bool) {
|
||||
if len(file.Blocks) == 0 || file.Size == 0 {
|
||||
return protocol.FileInfo{}, false
|
||||
}
|
||||
@ -763,7 +764,7 @@ func (f *folder) findRename(snap *db.Snapshot, mtimefs fs.Filesystem, file proto
|
||||
return true
|
||||
}
|
||||
|
||||
if !osutil.IsDeleted(mtimefs, fi.Name) {
|
||||
if !osutil.IsDeleted(f.mtimefs, fi.Name) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -27,8 +27,8 @@ type receiveEncryptedFolder struct {
|
||||
*sendReceiveFolder
|
||||
}
|
||||
|
||||
func newReceiveEncryptedFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, ver versioner.Versioner, fs fs.Filesystem, evLogger events.Logger, ioLimiter *byteSemaphore) service {
|
||||
return &receiveEncryptedFolder{newSendReceiveFolder(model, fset, ignores, cfg, ver, fs, evLogger, ioLimiter).(*sendReceiveFolder)}
|
||||
func newReceiveEncryptedFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, ver versioner.Versioner, evLogger events.Logger, ioLimiter *byteSemaphore) service {
|
||||
return &receiveEncryptedFolder{newSendReceiveFolder(model, fset, ignores, cfg, ver, evLogger, ioLimiter).(*sendReceiveFolder)}
|
||||
}
|
||||
|
||||
func (f *receiveEncryptedFolder) Revert() {
|
||||
@ -65,7 +65,7 @@ func (f *receiveEncryptedFolder) revert() {
|
||||
return true
|
||||
}
|
||||
|
||||
if err := f.inWritableDir(f.fs.Remove, fit.Name); err != nil && !fs.IsNotExist(err) {
|
||||
if err := f.inWritableDir(f.mtimefs.Remove, fit.Name); err != nil && !fs.IsNotExist(err) {
|
||||
f.newScanError(fit.Name, fmt.Errorf("deleting unexpected item: %w", err))
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,6 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/ignore"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/versioner"
|
||||
@ -57,8 +56,8 @@ type receiveOnlyFolder struct {
|
||||
*sendReceiveFolder
|
||||
}
|
||||
|
||||
func newReceiveOnlyFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, ver versioner.Versioner, fs fs.Filesystem, evLogger events.Logger, ioLimiter *byteSemaphore) service {
|
||||
sr := newSendReceiveFolder(model, fset, ignores, cfg, ver, fs, evLogger, ioLimiter).(*sendReceiveFolder)
|
||||
func newReceiveOnlyFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, ver versioner.Versioner, evLogger events.Logger, ioLimiter *byteSemaphore) service {
|
||||
sr := newSendReceiveFolder(model, fset, ignores, cfg, ver, evLogger, ioLimiter).(*sendReceiveFolder)
|
||||
sr.localFlags = protocol.FlagLocalReceiveOnly // gets propagated to the scanner, and set on locally changed files
|
||||
return &receiveOnlyFolder{sr}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/ignore"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/versioner"
|
||||
@ -24,7 +23,7 @@ type sendOnlyFolder struct {
|
||||
folder
|
||||
}
|
||||
|
||||
func newSendOnlyFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, _ versioner.Versioner, _ fs.Filesystem, evLogger events.Logger, ioLimiter *byteSemaphore) service {
|
||||
func newSendOnlyFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, _ versioner.Versioner, evLogger events.Logger, ioLimiter *byteSemaphore) service {
|
||||
f := &sendOnlyFolder{
|
||||
folder: newFolder(model, fset, ignores, cfg, evLogger, ioLimiter, nil),
|
||||
}
|
||||
|
@ -121,8 +121,6 @@ type dbUpdateJob struct {
|
||||
type sendReceiveFolder struct {
|
||||
folder
|
||||
|
||||
fs fs.Filesystem
|
||||
|
||||
queue *jobQueue
|
||||
blockPullReorderer blockPullReorderer
|
||||
writeLimiter *byteSemaphore
|
||||
@ -130,10 +128,9 @@ type sendReceiveFolder struct {
|
||||
tempPullErrors map[string]string // pull errors that might be just transient
|
||||
}
|
||||
|
||||
func newSendReceiveFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, ver versioner.Versioner, fs fs.Filesystem, evLogger events.Logger, ioLimiter *byteSemaphore) service {
|
||||
func newSendReceiveFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, ver versioner.Versioner, evLogger events.Logger, ioLimiter *byteSemaphore) service {
|
||||
f := &sendReceiveFolder{
|
||||
folder: newFolder(model, fset, ignores, cfg, evLogger, ioLimiter, ver),
|
||||
fs: fs,
|
||||
queue: newJobQueue(),
|
||||
blockPullReorderer: newBlockPullReorderer(cfg.BlockPullOrder, model.id, cfg.DeviceIDs()),
|
||||
writeLimiter: newByteSemaphore(cfg.MaxConcurrentWrites),
|
||||
@ -578,7 +575,7 @@ func (f *sendReceiveFolder) handleDir(file protocol.FileInfo, snap *db.Snapshot,
|
||||
l.Debugf("need dir\n\t%v\n\t%v", file, curFile)
|
||||
}
|
||||
|
||||
info, err := f.fs.Lstat(file.Name)
|
||||
info, err := f.mtimefs.Lstat(file.Name)
|
||||
switch {
|
||||
// There is already something under that name, we need to handle that.
|
||||
// Unless it already is a directory, as we only track permissions,
|
||||
@ -617,7 +614,7 @@ func (f *sendReceiveFolder) handleDir(file protocol.FileInfo, snap *db.Snapshot,
|
||||
// we can pass it to InWritableDir. We use a regular Mkdir and
|
||||
// not MkdirAll because the parent should already exist.
|
||||
mkdir := func(path string) error {
|
||||
err = f.fs.Mkdir(path, mode)
|
||||
err = f.mtimefs.Mkdir(path, mode)
|
||||
if err != nil || f.IgnorePerms || file.NoPermissions {
|
||||
return err
|
||||
}
|
||||
@ -628,14 +625,14 @@ func (f *sendReceiveFolder) handleDir(file protocol.FileInfo, snap *db.Snapshot,
|
||||
}
|
||||
|
||||
// Stat the directory so we can check its permissions.
|
||||
info, err := f.fs.Lstat(path)
|
||||
info, err := f.mtimefs.Lstat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Mask for the bits we want to preserve and add them in to the
|
||||
// directories permissions.
|
||||
return f.fs.Chmod(path, mode|(info.Mode()&retainBits))
|
||||
return f.mtimefs.Chmod(path, mode|(info.Mode()&retainBits))
|
||||
}
|
||||
|
||||
if err = f.inWritableDir(mkdir, file.Name); err == nil {
|
||||
@ -655,7 +652,7 @@ func (f *sendReceiveFolder) handleDir(file protocol.FileInfo, snap *db.Snapshot,
|
||||
// don't handle modification times on directories, because that sucks...)
|
||||
// It's OK to change mode bits on stuff within non-writable directories.
|
||||
if !f.IgnorePerms && !file.NoPermissions {
|
||||
if err := f.fs.Chmod(file.Name, mode|(info.Mode()&retainBits)); err != nil {
|
||||
if err := f.mtimefs.Chmod(file.Name, mode|(info.Mode()&retainBits)); err != nil {
|
||||
f.newPullError(file.Name, err)
|
||||
return
|
||||
}
|
||||
@ -668,7 +665,7 @@ func (f *sendReceiveFolder) handleDir(file protocol.FileInfo, snap *db.Snapshot,
|
||||
func (f *sendReceiveFolder) checkParent(file string, scanChan chan<- string) bool {
|
||||
parent := filepath.Dir(file)
|
||||
|
||||
if err := osutil.TraversesSymlink(f.fs, parent); err != nil {
|
||||
if err := osutil.TraversesSymlink(f.mtimefs, parent); err != nil {
|
||||
f.newPullError(file, errors.Wrap(err, "checking parent dirs"))
|
||||
return false
|
||||
}
|
||||
@ -688,12 +685,12 @@ func (f *sendReceiveFolder) checkParent(file string, scanChan chan<- string) boo
|
||||
// And if this is an encrypted folder:
|
||||
// Encrypted files have made-up filenames with two synthetic parent
|
||||
// directories which don't have any meaning. Create those if necessary.
|
||||
if _, err := f.fs.Lstat(parent); !fs.IsNotExist(err) {
|
||||
if _, err := f.mtimefs.Lstat(parent); !fs.IsNotExist(err) {
|
||||
l.Debugf("%v parent not missing %v", f, file)
|
||||
return true
|
||||
}
|
||||
l.Debugf("%v creating parent directory of %v", f, file)
|
||||
if err := f.fs.MkdirAll(parent, 0755); err != nil {
|
||||
if err := f.mtimefs.MkdirAll(parent, 0755); err != nil {
|
||||
f.newPullError(file, errors.Wrap(err, "creating parent dir"))
|
||||
return false
|
||||
}
|
||||
@ -746,7 +743,7 @@ func (f *sendReceiveFolder) handleSymlink(file protocol.FileInfo, snap *db.Snaps
|
||||
// We declare a function that acts on only the path name, so
|
||||
// we can pass it to InWritableDir.
|
||||
createLink := func(path string) error {
|
||||
if err := f.fs.CreateSymlink(file.SymlinkTarget, path); err != nil {
|
||||
if err := f.mtimefs.CreateSymlink(file.SymlinkTarget, path); err != nil {
|
||||
return err
|
||||
}
|
||||
return f.maybeCopyOwner(path)
|
||||
@ -761,7 +758,7 @@ func (f *sendReceiveFolder) handleSymlink(file protocol.FileInfo, snap *db.Snaps
|
||||
|
||||
func (f *sendReceiveFolder) handleSymlinkCheckExisting(file protocol.FileInfo, snap *db.Snapshot, scanChan chan<- string) error {
|
||||
// If there is already something under that name, we need to handle that.
|
||||
info, err := f.fs.Lstat(file.Name)
|
||||
info, err := f.mtimefs.Lstat(file.Name)
|
||||
if err != nil {
|
||||
if fs.IsNotExist(err) {
|
||||
return nil
|
||||
@ -892,7 +889,7 @@ func (f *sendReceiveFolder) deleteFileWithCurrent(file, cur protocol.FileInfo, h
|
||||
if f.versioner != nil && !cur.IsSymlink() {
|
||||
err = f.inWritableDir(f.versioner.Archive, file.Name)
|
||||
} else {
|
||||
err = f.inWritableDir(f.fs.Remove, file.Name)
|
||||
err = f.inWritableDir(f.mtimefs.Remove, file.Name)
|
||||
}
|
||||
|
||||
if err == nil || fs.IsNotExist(err) {
|
||||
@ -901,7 +898,7 @@ func (f *sendReceiveFolder) deleteFileWithCurrent(file, cur protocol.FileInfo, h
|
||||
return
|
||||
}
|
||||
|
||||
if _, serr := f.fs.Lstat(file.Name); serr != nil && !fs.IsPermission(serr) {
|
||||
if _, serr := f.mtimefs.Lstat(file.Name); serr != nil && !fs.IsPermission(serr) {
|
||||
// We get an error just looking at the file, and it's not a permission
|
||||
// problem. Lets assume the error is in fact some variant of "file
|
||||
// does not exist" (possibly expressed as some parent being a file and
|
||||
@ -956,7 +953,7 @@ func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, sn
|
||||
}
|
||||
// Check that the target corresponds to what we have in the DB
|
||||
curTarget, ok := snap.Get(protocol.LocalDeviceID, target.Name)
|
||||
switch stat, serr := f.fs.Lstat(target.Name); {
|
||||
switch stat, serr := f.mtimefs.Lstat(target.Name); {
|
||||
case serr != nil:
|
||||
var caseErr *fs.ErrCaseConflict
|
||||
switch {
|
||||
@ -983,7 +980,7 @@ func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, sn
|
||||
err = errModified
|
||||
default:
|
||||
var fi protocol.FileInfo
|
||||
if fi, err = scanner.CreateFileInfo(stat, target.Name, f.fs); err == nil {
|
||||
if fi, err = scanner.CreateFileInfo(stat, target.Name, f.mtimefs); err == nil {
|
||||
if !fi.IsEquivalentOptional(curTarget, f.modTimeWindow, f.IgnorePerms, true, protocol.LocalAllFlags) {
|
||||
// Target changed
|
||||
scanChan <- target.Name
|
||||
@ -1000,13 +997,13 @@ func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, sn
|
||||
if f.versioner != nil {
|
||||
err = f.CheckAvailableSpace(uint64(source.Size))
|
||||
if err == nil {
|
||||
err = osutil.Copy(f.CopyRangeMethod, f.fs, f.fs, source.Name, tempName)
|
||||
err = osutil.Copy(f.CopyRangeMethod, f.mtimefs, f.mtimefs, source.Name, tempName)
|
||||
if err == nil {
|
||||
err = f.inWritableDir(f.versioner.Archive, source.Name)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = osutil.RenameOrCopy(f.CopyRangeMethod, f.fs, f.fs, source.Name, tempName)
|
||||
err = osutil.RenameOrCopy(f.CopyRangeMethod, f.mtimefs, f.mtimefs, source.Name, tempName)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
@ -1081,12 +1078,12 @@ func (f *sendReceiveFolder) handleFile(file protocol.FileInfo, snap *db.Snapshot
|
||||
|
||||
// Check for an old temporary file which might have some blocks we could
|
||||
// reuse.
|
||||
tempBlocks, err := scanner.HashFile(f.ctx, f.fs, tempName, file.BlockSize(), nil, false)
|
||||
tempBlocks, err := scanner.HashFile(f.ctx, f.mtimefs, tempName, file.BlockSize(), nil, false)
|
||||
if err != nil {
|
||||
var caseErr *fs.ErrCaseConflict
|
||||
if errors.As(err, &caseErr) {
|
||||
if rerr := f.fs.Rename(caseErr.Real, tempName); rerr == nil {
|
||||
tempBlocks, err = scanner.HashFile(f.ctx, f.fs, tempName, file.BlockSize(), nil, false)
|
||||
if rerr := f.mtimefs.Rename(caseErr.Real, tempName); rerr == nil {
|
||||
tempBlocks, err = scanner.HashFile(f.ctx, f.mtimefs, tempName, file.BlockSize(), nil, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1116,7 +1113,7 @@ func (f *sendReceiveFolder) handleFile(file protocol.FileInfo, snap *db.Snapshot
|
||||
// Otherwise, discard the file ourselves in order for the
|
||||
// sharedpuller not to panic when it fails to exclusively create a
|
||||
// file which already exists
|
||||
f.inWritableDir(f.fs.Remove, tempName)
|
||||
f.inWritableDir(f.mtimefs.Remove, tempName)
|
||||
}
|
||||
} else {
|
||||
// Copy the blocks, as we don't want to shuffle them on the FileInfo
|
||||
@ -1133,7 +1130,7 @@ func (f *sendReceiveFolder) handleFile(file protocol.FileInfo, snap *db.Snapshot
|
||||
"action": "update",
|
||||
})
|
||||
|
||||
s := newSharedPullerState(file, f.fs, f.folderID, tempName, blocks, reused, f.IgnorePerms || file.NoPermissions, hasCurFile, curFile, !f.DisableSparseFiles, !f.DisableFsync)
|
||||
s := newSharedPullerState(file, f.mtimefs, f.folderID, tempName, blocks, reused, f.IgnorePerms || file.NoPermissions, hasCurFile, curFile, !f.DisableSparseFiles, !f.DisableFsync)
|
||||
|
||||
l.Debugf("%v need file %s; copy %d, reused %v", f, file.Name, len(blocks), len(reused))
|
||||
|
||||
@ -1208,13 +1205,13 @@ func (f *sendReceiveFolder) shortcutFile(file, curFile protocol.FileInfo, dbUpda
|
||||
f.queue.Done(file.Name)
|
||||
|
||||
if !f.IgnorePerms && !file.NoPermissions {
|
||||
if err = f.fs.Chmod(file.Name, fs.FileMode(file.Permissions&0777)); err != nil {
|
||||
if err = f.mtimefs.Chmod(file.Name, fs.FileMode(file.Permissions&0777)); err != nil {
|
||||
f.newPullError(file.Name, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
f.fs.Chtimes(file.Name, file.ModTime(), file.ModTime()) // never fails
|
||||
f.mtimefs.Chtimes(file.Name, file.ModTime(), file.ModTime()) // never fails
|
||||
|
||||
dbUpdateChan <- dbUpdateJob{file, dbUpdateShortcutFile}
|
||||
}
|
||||
@ -1403,7 +1400,7 @@ func (f *sendReceiveFolder) initWeakHashFinder(state copyBlocksState) (*weakhash
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
file, err := f.fs.Open(state.file.Name)
|
||||
file, err := f.mtimefs.Open(state.file.Name)
|
||||
if err != nil {
|
||||
l.Debugln("weak hasher", err)
|
||||
return nil, nil
|
||||
@ -1551,7 +1548,7 @@ func (f *sendReceiveFolder) pullBlock(state pullBlockState, out chan<- *sharedPu
|
||||
func (f *sendReceiveFolder) performFinish(file, curFile protocol.FileInfo, hasCurFile bool, tempName string, snap *db.Snapshot, dbUpdateChan chan<- dbUpdateJob, scanChan chan<- string) error {
|
||||
// Set the correct permission bits on the new file
|
||||
if !f.IgnorePerms && !file.NoPermissions {
|
||||
if err := f.fs.Chmod(tempName, fs.FileMode(file.Permissions&0777)); err != nil {
|
||||
if err := f.mtimefs.Chmod(tempName, fs.FileMode(file.Permissions&0777)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -1561,7 +1558,7 @@ func (f *sendReceiveFolder) performFinish(file, curFile protocol.FileInfo, hasCu
|
||||
return err
|
||||
}
|
||||
|
||||
if stat, err := f.fs.Lstat(file.Name); err == nil {
|
||||
if stat, err := f.mtimefs.Lstat(file.Name); err == nil {
|
||||
// There is an old file or directory already in place. We need to
|
||||
// handle that.
|
||||
|
||||
@ -1590,12 +1587,12 @@ func (f *sendReceiveFolder) performFinish(file, curFile protocol.FileInfo, hasCu
|
||||
|
||||
// Replace the original content with the new one. If it didn't work,
|
||||
// leave the temp file in place for reuse.
|
||||
if err := osutil.RenameOrCopy(f.CopyRangeMethod, f.fs, f.fs, tempName, file.Name); err != nil {
|
||||
if err := osutil.RenameOrCopy(f.CopyRangeMethod, f.mtimefs, f.mtimefs, tempName, file.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set the correct timestamp on the new file
|
||||
f.fs.Chtimes(file.Name, file.ModTime(), file.ModTime()) // never fails
|
||||
f.mtimefs.Chtimes(file.Name, file.ModTime(), file.ModTime()) // never fails
|
||||
|
||||
// Record the updated file in the index
|
||||
dbUpdateChan <- dbUpdateJob{file, dbUpdateHandleFile}
|
||||
@ -1671,7 +1668,7 @@ func (f *sendReceiveFolder) dbUpdaterRoutine(dbUpdateChan <-chan dbUpdateJob) {
|
||||
for dir := range changedDirs {
|
||||
delete(changedDirs, dir)
|
||||
if !f.FolderConfiguration.DisableFsync {
|
||||
fd, err := f.fs.Open(dir)
|
||||
fd, err := f.mtimefs.Open(dir)
|
||||
if err != nil {
|
||||
l.Debugf("fsync %q failed: %v", dir, err)
|
||||
continue
|
||||
@ -1786,21 +1783,21 @@ func removeAvailability(availabilities []Availability, availability Availability
|
||||
func (f *sendReceiveFolder) moveForConflict(name, lastModBy string, scanChan chan<- string) error {
|
||||
if isConflict(name) {
|
||||
l.Infoln("Conflict for", name, "which is already a conflict copy; not copying again.")
|
||||
if err := f.fs.Remove(name); err != nil && !fs.IsNotExist(err) {
|
||||
if err := f.mtimefs.Remove(name); err != nil && !fs.IsNotExist(err) {
|
||||
return errors.Wrap(err, contextRemovingOldItem)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if f.MaxConflicts == 0 {
|
||||
if err := f.fs.Remove(name); err != nil && !fs.IsNotExist(err) {
|
||||
if err := f.mtimefs.Remove(name); err != nil && !fs.IsNotExist(err) {
|
||||
return errors.Wrap(err, contextRemovingOldItem)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
newName := conflictName(name, lastModBy)
|
||||
err := f.fs.Rename(name, newName)
|
||||
err := f.mtimefs.Rename(name, newName)
|
||||
if fs.IsNotExist(err) {
|
||||
// We were supposed to move a file away but it does not exist. Either
|
||||
// the user has already moved it away, or the conflict was between a
|
||||
@ -1809,11 +1806,11 @@ func (f *sendReceiveFolder) moveForConflict(name, lastModBy string, scanChan cha
|
||||
err = nil
|
||||
}
|
||||
if f.MaxConflicts > -1 {
|
||||
matches := existingConflicts(name, f.fs)
|
||||
matches := existingConflicts(name, f.mtimefs)
|
||||
if len(matches) > f.MaxConflicts {
|
||||
sort.Sort(sort.Reverse(sort.StringSlice(matches)))
|
||||
for _, match := range matches[f.MaxConflicts:] {
|
||||
if gerr := f.fs.Remove(match); gerr != nil {
|
||||
if gerr := f.mtimefs.Remove(match); gerr != nil {
|
||||
l.Debugln(f, "removing extra conflict", gerr)
|
||||
}
|
||||
}
|
||||
@ -1871,17 +1868,17 @@ func (f *sendReceiveFolder) deleteItemOnDisk(item protocol.FileInfo, snap *db.Sn
|
||||
return f.inWritableDir(f.versioner.Archive, item.Name)
|
||||
}
|
||||
|
||||
return f.inWritableDir(f.fs.Remove, item.Name)
|
||||
return f.inWritableDir(f.mtimefs.Remove, item.Name)
|
||||
}
|
||||
|
||||
// deleteDirOnDisk attempts to delete a directory. It checks for files/dirs inside
|
||||
// the directory and removes them if possible or returns an error if it fails
|
||||
func (f *sendReceiveFolder) deleteDirOnDisk(dir string, snap *db.Snapshot, scanChan chan<- string) error {
|
||||
if err := osutil.TraversesSymlink(f.fs, filepath.Dir(dir)); err != nil {
|
||||
if err := osutil.TraversesSymlink(f.mtimefs, filepath.Dir(dir)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
files, _ := f.fs.DirNames(dir)
|
||||
files, _ := f.mtimefs.DirNames(dir)
|
||||
|
||||
toBeDeleted := make([]string, 0, len(files))
|
||||
|
||||
@ -1910,10 +1907,10 @@ func (f *sendReceiveFolder) deleteDirOnDisk(dir string, snap *db.Snapshot, scanC
|
||||
hasReceiveOnlyChanged = true
|
||||
continue
|
||||
}
|
||||
info, err := f.fs.Lstat(fullDirFile)
|
||||
info, err := f.mtimefs.Lstat(fullDirFile)
|
||||
var diskFile protocol.FileInfo
|
||||
if err == nil {
|
||||
diskFile, err = scanner.CreateFileInfo(info, fullDirFile, f.fs)
|
||||
diskFile, err = scanner.CreateFileInfo(info, fullDirFile, f.mtimefs)
|
||||
}
|
||||
if err != nil {
|
||||
// Lets just assume the file has changed.
|
||||
@ -1950,15 +1947,15 @@ func (f *sendReceiveFolder) deleteDirOnDisk(dir string, snap *db.Snapshot, scanC
|
||||
}
|
||||
|
||||
for _, del := range toBeDeleted {
|
||||
f.fs.RemoveAll(del)
|
||||
f.mtimefs.RemoveAll(del)
|
||||
}
|
||||
|
||||
err := f.inWritableDir(f.fs.Remove, dir)
|
||||
err := f.inWritableDir(f.mtimefs.Remove, dir)
|
||||
if err == nil || fs.IsNotExist(err) {
|
||||
// It was removed or it doesn't exist to start with
|
||||
return nil
|
||||
}
|
||||
if _, serr := f.fs.Lstat(dir); serr != nil && !fs.IsPermission(serr) {
|
||||
if _, serr := f.mtimefs.Lstat(dir); serr != nil && !fs.IsPermission(serr) {
|
||||
// We get an error just looking at the directory, and it's not a
|
||||
// permission problem. Lets assume the error is in fact some variant
|
||||
// of "file does not exist" (possibly expressed as some parent being a
|
||||
@ -1988,7 +1985,7 @@ func (f *sendReceiveFolder) scanIfItemChanged(name string, stat fs.FileInfo, ite
|
||||
// to the database. If there's a mismatch here, there might be local
|
||||
// changes that we don't know about yet and we should scan before
|
||||
// touching the item.
|
||||
statItem, err := scanner.CreateFileInfo(stat, item.Name, f.fs)
|
||||
statItem, err := scanner.CreateFileInfo(stat, item.Name, f.mtimefs)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "comparing item on disk to db")
|
||||
}
|
||||
@ -2004,12 +2001,12 @@ func (f *sendReceiveFolder) scanIfItemChanged(name string, stat fs.FileInfo, ite
|
||||
// in the DB before the caller proceeds with actually deleting it.
|
||||
// I.e. non-nil error status means "Do not delete!" or "is already deleted".
|
||||
func (f *sendReceiveFolder) checkToBeDeleted(file, cur protocol.FileInfo, hasCur bool, scanChan chan<- string) error {
|
||||
if err := osutil.TraversesSymlink(f.fs, filepath.Dir(file.Name)); err != nil {
|
||||
if err := osutil.TraversesSymlink(f.mtimefs, filepath.Dir(file.Name)); err != nil {
|
||||
l.Debugln(f, "not deleting item behind symlink on disk, but update db", file.Name)
|
||||
return fs.ErrNotExist
|
||||
}
|
||||
|
||||
stat, err := f.fs.Lstat(file.Name)
|
||||
stat, err := f.mtimefs.Lstat(file.Name)
|
||||
deleted := fs.IsNotExist(err) || fs.IsErrCaseConflict(err)
|
||||
if !deleted && err != nil {
|
||||
return err
|
||||
@ -2036,18 +2033,18 @@ func (f *sendReceiveFolder) maybeCopyOwner(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
info, err := f.fs.Lstat(filepath.Dir(path))
|
||||
info, err := f.mtimefs.Lstat(filepath.Dir(path))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "copy owner from parent")
|
||||
}
|
||||
if err := f.fs.Lchown(path, info.Owner(), info.Group()); err != nil {
|
||||
if err := f.mtimefs.Lchown(path, info.Owner(), info.Group()); err != nil {
|
||||
return errors.Wrap(err, "copy owner from parent")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *sendReceiveFolder) inWritableDir(fn func(string) error, path string) error {
|
||||
return inWritableDir(fn, f.fs, path, f.IgnorePerms)
|
||||
return inWritableDir(fn, f.mtimefs, path, f.IgnorePerms)
|
||||
}
|
||||
|
||||
func (f *sendReceiveFolder) limitedWriteAt(fd io.WriterAt, data []byte, offset int64) error {
|
||||
|
@ -807,12 +807,13 @@ func TestCopyOwner(t *testing.T) {
|
||||
f.folder.FolderConfiguration = config.NewFolderConfiguration(m.id, f.ID, f.Label, fs.FilesystemTypeFake, "/TestCopyOwner")
|
||||
f.folder.FolderConfiguration.CopyOwnershipFromParent = true
|
||||
|
||||
f.fs = f.Filesystem()
|
||||
f.fset = newFileSet(t, f.ID, f.Filesystem(), m.db)
|
||||
f.mtimefs = f.fset.MtimeFS()
|
||||
|
||||
// Create a parent dir with a certain owner/group.
|
||||
|
||||
f.fs.Mkdir("foo", 0755)
|
||||
f.fs.Lchown("foo", expOwner, expGroup)
|
||||
f.mtimefs.Mkdir("foo", 0755)
|
||||
f.mtimefs.Lchown("foo", expOwner, expGroup)
|
||||
|
||||
dir := protocol.FileInfo{
|
||||
Name: "foo/bar",
|
||||
@ -833,7 +834,7 @@ func TestCopyOwner(t *testing.T) {
|
||||
t.Fatal("Unexpected receive on scanChan:", toScan)
|
||||
}
|
||||
|
||||
info, err := f.fs.Lstat("foo/bar")
|
||||
info, err := f.mtimefs.Lstat("foo/bar")
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error (dir):", err)
|
||||
}
|
||||
@ -869,7 +870,7 @@ func TestCopyOwner(t *testing.T) {
|
||||
f.handleFile(file, snap, copierChan)
|
||||
<-dbUpdateChan
|
||||
|
||||
info, err = f.fs.Lstat("foo/bar/baz")
|
||||
info, err = f.mtimefs.Lstat("foo/bar/baz")
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error (file):", err)
|
||||
}
|
||||
@ -892,7 +893,7 @@ func TestCopyOwner(t *testing.T) {
|
||||
t.Fatal("Unexpected receive on scanChan:", toScan)
|
||||
}
|
||||
|
||||
info, err = f.fs.Lstat("foo/bar/sym")
|
||||
info, err = f.mtimefs.Lstat("foo/bar/sym")
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error (file):", err)
|
||||
}
|
||||
@ -1215,7 +1216,7 @@ func TestPullTempFileCaseConflict(t *testing.T) {
|
||||
file := protocol.FileInfo{Name: "foo"}
|
||||
confl := "Foo"
|
||||
tempNameConfl := fs.TempName(confl)
|
||||
if fd, err := f.fs.Create(tempNameConfl); err != nil {
|
||||
if fd, err := f.mtimefs.Create(tempNameConfl); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if _, err := fd.Write([]byte("data")); err != nil {
|
||||
@ -1239,7 +1240,7 @@ func TestPullCaseOnlyRename(t *testing.T) {
|
||||
// tempNameConfl := fs.TempName(confl)
|
||||
|
||||
name := "foo"
|
||||
if fd, err := f.fs.Create(name); err != nil {
|
||||
if fd, err := f.mtimefs.Create(name); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if _, err := fd.Write([]byte("data")); err != nil {
|
||||
@ -1280,7 +1281,7 @@ func TestPullSymlinkOverExistingWindows(t *testing.T) {
|
||||
defer cleanupSRFolder(f, m)
|
||||
|
||||
name := "foo"
|
||||
if fd, err := f.fs.Create(name); err != nil {
|
||||
if fd, err := f.mtimefs.Create(name); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if _, err := fd.Write([]byte("data")); err != nil {
|
||||
@ -1308,7 +1309,7 @@ func TestPullSymlinkOverExistingWindows(t *testing.T) {
|
||||
} else if !file.IsUnsupported() {
|
||||
t.Error("symlink entry isn't marked as unsupported")
|
||||
}
|
||||
if _, err := f.fs.Lstat(name); err == nil {
|
||||
if _, err := f.mtimefs.Lstat(name); err == nil {
|
||||
t.Error("old file still exists on disk")
|
||||
} else if !fs.IsNotExist(err) {
|
||||
t.Error(err)
|
||||
@ -1324,7 +1325,7 @@ func TestPullDeleteCaseConflict(t *testing.T) {
|
||||
dbUpdateChan := make(chan dbUpdateJob, 1)
|
||||
scanChan := make(chan string)
|
||||
|
||||
if fd, err := f.fs.Create(name); err != nil {
|
||||
if fd, err := f.mtimefs.Create(name); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if _, err := fd.Write([]byte("data")); err != nil {
|
||||
|
@ -164,7 +164,7 @@ type model struct {
|
||||
started chan struct{}
|
||||
}
|
||||
|
||||
type folderFactory func(*model, *db.FileSet, *ignore.Matcher, config.FolderConfiguration, versioner.Versioner, fs.Filesystem, events.Logger, *byteSemaphore) service
|
||||
type folderFactory func(*model, *db.FileSet, *ignore.Matcher, config.FolderConfiguration, versioner.Versioner, events.Logger, *byteSemaphore) service
|
||||
|
||||
var (
|
||||
folderFactories = make(map[config.FolderType]folderFactory)
|
||||
@ -384,8 +384,6 @@ func (m *model) addAndStartFolderLockedWithIgnores(cfg config.FolderConfiguratio
|
||||
}
|
||||
}
|
||||
|
||||
ffs := fset.MtimeFS()
|
||||
|
||||
if cfg.Type == config.FolderTypeReceiveEncrypted {
|
||||
if encryptionToken, err := readEncryptionToken(cfg); err == nil {
|
||||
m.folderEncryptionPasswordTokens[folder] = encryptionToken
|
||||
@ -395,6 +393,7 @@ func (m *model) addAndStartFolderLockedWithIgnores(cfg config.FolderConfiguratio
|
||||
}
|
||||
|
||||
// These are our metadata files, and they should always be hidden.
|
||||
ffs := cfg.Filesystem()
|
||||
_ = ffs.Hide(config.DefaultMarkerName)
|
||||
_ = ffs.Hide(".stversions")
|
||||
_ = ffs.Hide(".stignore")
|
||||
@ -409,7 +408,7 @@ func (m *model) addAndStartFolderLockedWithIgnores(cfg config.FolderConfiguratio
|
||||
}
|
||||
m.folderVersioners[folder] = ver
|
||||
|
||||
p := folderFactory(m, fset, ignores, cfg, ver, ffs, m.evLogger, m.folderIOLimiter)
|
||||
p := folderFactory(m, fset, ignores, cfg, ver, m.evLogger, m.folderIOLimiter)
|
||||
|
||||
m.folderRunners[folder] = p
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user