Skip to content

Commit

Permalink
operations: Fix "optional feature not implemented" error with a crypt…
Browse files Browse the repository at this point in the history
…ed sftp

Before this change operations.SetDirModTime could return the error
"optional feature not implemented" when attempting to set modification
times on crypted sftp backends.

This was because crypt wraps the directories using fs.DirWrapper but
these return fs.ErrorNotImplemented for the SetModTime method.

The fix is to recognise that error and fall back to using the
DirSetModTime method on the backend which does work.

Fixes rclone#7673
  • Loading branch information
ncw committed Mar 22, 2024
1 parent 5ee89bd commit ff855fe
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 3 deletions.
10 changes: 7 additions & 3 deletions fs/operations/operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -2628,11 +2628,15 @@ func SetDirModTime(ctx context.Context, f fs.Fs, dst fs.Directory, dir string, m
if dst != nil {
if do, ok := dst.(fs.SetModTimer); ok {
err := do.SetModTime(ctx, modTime)
if err != nil {
if errors.Is(err, fs.ErrorNotImplemented) {
// Fall through and run the code below if not implemented
// This can happen for fs.DirWrapper instances
} else if err != nil {
return dst, err
} else {
fs.Infof(logName, "Set directory modification time (using SetModTime)")
return dst, nil
}
fs.Infof(logName, "Set directory modification time (using SetModTime)")
return dst, nil
}
}

Expand Down
7 changes: 7 additions & 0 deletions fs/operations/operations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1787,6 +1787,13 @@ func TestSetDirModTime(t *testing.T) {
fstest.CheckDirModTime(ctx, t, r.Fremote, newDst, t2)
}
fstest.CheckDirModTime(ctx, t, r.Fremote, fstest.NewDirectory(ctx, t, r.Fremote, name), t2)

// Now wrap the directory to make the SetModTime method return fs.ErrorNotImplemented and check that it falls back correctly
wrappedDir := fs.NewDirWrapper(existingDir.Remote(), fs.NewDir(existingDir.Remote(), existingDir.ModTime(ctx)))
newDst, err = operations.SetDirModTime(ctx, r.Fremote, wrappedDir, "SHOULD BE IGNORED", t1)
require.NoError(t, err)
require.NotNil(t, newDst)
fstest.CheckDirModTime(ctx, t, r.Fremote, fstest.NewDirectory(ctx, t, r.Fremote, name), t1)
}

func TestDirsEqual(t *testing.T) {
Expand Down

0 comments on commit ff855fe

Please sign in to comment.