serve sftp: use the requested atime when setting file times

When a SETSTAT request set the access and modification times, the
handler passed the modification time for both, discarding the
requested access time. Pass the requested access time through instead.

The VFS currently ignores the atime, but it might use it one day.
This commit is contained in:
Nick Craig-Wood
2026-05-25 20:43:23 +01:00
parent 54cd7d6750
commit f71bebab44
2 changed files with 22 additions and 2 deletions
+3 -2
View File
@@ -76,8 +76,9 @@ func (v vfsHandler) Filecmd(r *sftp.Request) error {
}
}
if flags.Acmodtime {
modTime := time.Unix(int64(attr.Mtime), 0)
err := v.Chtimes(r.Filepath, modTime, modTime)
atime := time.Unix(int64(attr.Atime), 0)
mtime := time.Unix(int64(attr.Mtime), 0)
err := v.Chtimes(r.Filepath, atime, mtime)
if err != nil {
return err
}
+19
View File
@@ -12,6 +12,7 @@ import (
"os"
"strings"
"testing"
"time"
"github.com/pkg/sftp"
_ "github.com/rclone/rclone/backend/local"
@@ -183,6 +184,24 @@ func TestStatVFS(t *testing.T) {
assert.Equal(t, uint64(255), st.Namemax)
}
// Test that a SETSTAT request setting the modification time is honoured, even
// when the time happens to be the Unix epoch
func TestSetstatMtime(t *testing.T) {
vfsOpt := vfscommon.Opt
vfsOpt.CacheMode = vfscommon.CacheModeOff
client := startTestServer(t, &vfsOpt)
const fileName = "file.bin"
require.NoError(t, writeFile(client, fileName, "hello"))
epoch := time.Unix(0, 0)
require.NoError(t, client.Chtimes(fileName, epoch, epoch))
fi, err := client.Stat(fileName)
require.NoError(t, err)
assert.True(t, fi.ModTime().Equal(epoch), "mtime not applied: got %v want %v", fi.ModTime(), epoch)
}
// writeFile writes contents to fileName via the client truncating any existing
// data, the way a normal upload does.
func writeFile(client *sftp.Client, fileName, contents string) error {