improve chtimes handling on open files

This commit is contained in:
Nicola Murino 2021-11-26 19:00:44 +01:00
parent f828c58dca
commit f2480ce5c9
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB
8 changed files with 93 additions and 3 deletions

View file

@ -291,6 +291,7 @@ type ActiveTransfer interface {
SignalClose()
Truncate(fsPath string, size int64) (int64, error)
GetRealFsPath(fsPath string) string
SetTimes(fsPath string, atime time.Time, mtime time.Time) bool
}
// ActiveConnection defines the interface for the current active connections

View file

@ -201,6 +201,17 @@ func (c *BaseConnection) getRealFsPath(fsPath string) string {
return fsPath
}
func (c *BaseConnection) setTimes(fsPath string, atime time.Time, mtime time.Time) {
c.RLock()
defer c.RUnlock()
for _, t := range c.activeTransfers {
if t.SetTimes(fsPath, atime, mtime) {
return
}
}
}
func (c *BaseConnection) truncateOpenHandle(fsPath string, size int64) (int64, error) {
c.RLock()
defer c.RUnlock()
@ -558,6 +569,7 @@ func (c *BaseConnection) handleChtimes(fs vfs.Fs, fsPath, pathForPerms string, a
fsPath, attributes.Atime, attributes.Mtime, err)
return c.GetFsError(fs, err)
}
c.setTimes(fsPath, attributes.Atime, attributes.Mtime)
accessTimeString := attributes.Atime.Format(chtimesFormat)
modificationTimeString := attributes.Mtime.Format(chtimesFormat)
logger.CommandLog(chtimesLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1,

View file

@ -321,6 +321,58 @@ func TestSetStat(t *testing.T) {
assert.NoError(t, err)
}
func TestChtimesOpenHandle(t *testing.T) {
localUser, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
assert.NoError(t, err)
sftpUser, _, err := httpdtest.AddUser(getTestSFTPUser(), http.StatusCreated)
assert.NoError(t, err)
u := getCryptFsUser()
u.Username += "_crypt"
cryptFsUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
assert.NoError(t, err)
for _, user := range []dataprovider.User{localUser, sftpUser, cryptFsUser} {
conn, client, err := getSftpClient(user)
if assert.NoError(t, err) {
defer conn.Close()
defer client.Close()
f, err := client.Create(testFileName)
assert.NoError(t, err, "user %v", user.Username)
f1, err := client.Create(testFileName + "1")
assert.NoError(t, err, "user %v", user.Username)
acmodTime := time.Now().Add(36 * time.Hour)
err = client.Chtimes(testFileName, acmodTime, acmodTime)
assert.NoError(t, err, "user %v", user.Username)
_, err = f.Write(testFileContent)
assert.NoError(t, err, "user %v", user.Username)
err = f.Close()
assert.NoError(t, err, "user %v", user.Username)
err = f1.Close()
assert.NoError(t, err, "user %v", user.Username)
info, err := client.Lstat(testFileName)
assert.NoError(t, err, "user %v", user.Username)
diff := math.Abs(info.ModTime().Sub(acmodTime).Seconds())
assert.LessOrEqual(t, diff, float64(1), "user %v", user.Username)
info1, err := client.Lstat(testFileName + "1")
assert.NoError(t, err, "user %v", user.Username)
diff = math.Abs(info1.ModTime().Sub(acmodTime).Seconds())
assert.Greater(t, diff, float64(86400), "user %v", user.Username)
}
}
_, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
assert.NoError(t, err)
_, err = httpdtest.RemoveUser(localUser, http.StatusOK)
assert.NoError(t, err)
err = os.RemoveAll(localUser.GetHomeDir())
assert.NoError(t, err)
_, err = httpdtest.RemoveUser(cryptFsUser, http.StatusOK)
assert.NoError(t, err)
err = os.RemoveAll(cryptFsUser.GetHomeDir())
assert.NoError(t, err)
}
func TestPermissionErrors(t *testing.T) {
user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
assert.NoError(t, err)

View file

@ -38,6 +38,8 @@ type BaseTransfer struct { //nolint:maligned
isNewFile bool
transferType int
AbortTransfer int32
aTime time.Time
mTime time.Time
sync.Mutex
ErrTransfer error
}
@ -115,6 +117,15 @@ func (t *BaseTransfer) GetFsPath() string {
return t.fsPath
}
func (t *BaseTransfer) SetTimes(fsPath string, atime time.Time, mtime time.Time) bool {
if fsPath == t.GetFsPath() {
t.aTime = atime
t.mTime = mtime
return true
}
return false
}
// GetRealFsPath returns the real transfer filesystem path.
// If atomic uploads are enabled this differ from fsPath
func (t *BaseTransfer) GetRealFsPath(fsPath string) string {
@ -252,6 +263,7 @@ func (t *BaseTransfer) Close() error {
}
t.Connection.Log(logger.LevelDebug, "uploaded file size %v", fileSize)
t.updateQuota(numFiles, fileSize)
t.updateTimes()
logger.TransferLog(uploadLogSender, t.fsPath, elapsed, atomic.LoadInt64(&t.BytesReceived), t.Connection.User.Username,
t.Connection.ID, t.Connection.protocol, t.Connection.localAddr, t.Connection.remoteAddr, t.ftpMode)
ExecuteActionNotification(&t.Connection.User, operationUpload, t.fsPath, t.requestPath, "", "", "", t.Connection.protocol,
@ -266,6 +278,14 @@ func (t *BaseTransfer) Close() error {
return err
}
func (t *BaseTransfer) updateTimes() {
if !t.aTime.IsZero() && !t.mTime.IsZero() {
err := t.Fs.Chtimes(t.fsPath, t.aTime, t.mTime)
t.Connection.Log(logger.LevelDebug, "set times for file %#v, atime: %v, mtime: %v, err: %v",
t.fsPath, t.aTime, t.mTime, err)
}
}
func (t *BaseTransfer) updateQuota(numFiles int, fileSize int64) bool {
// S3 uploads are atomic, if there is an error nothing is uploaded
if t.File == nil && t.ErrTransfer != nil {

View file

@ -84,6 +84,7 @@ Flags:
--s3-acl string
--s3-bucket string
--s3-endpoint string
--s3-force-path-style Force path style bucket URL
--s3-key-prefix string Allows to restrict access to the
virtual folder identified by this
prefix and its contents

View file

@ -9762,6 +9762,8 @@ func getScpDownloadCommand(localPath, remotePath string, preserveTime, recursive
args = append(args, "2022")
args = append(args, "-o")
args = append(args, "StrictHostKeyChecking=no")
args = append(args, "-o")
args = append(args, "HostKeyAlgorithms=+ssh-rsa")
args = append(args, "-i")
args = append(args, privateKeyPath)
args = append(args, remotePath)
@ -9787,6 +9789,8 @@ func getScpUploadCommand(localPath, remotePath string, preserveTime, remoteToRem
args = append(args, "2022")
args = append(args, "-o")
args = append(args, "StrictHostKeyChecking=no")
args = append(args, "-o")
args = append(args, "HostKeyAlgorithms=+ssh-rsa")
args = append(args, "-i")
args = append(args, privateKeyPath)
args = append(args, localPath)

View file

@ -232,7 +232,7 @@ function deleteAction() {
},
{
"targets": [2],
"render": $.fn.dataTable.render.ellipsis(50, true),
"render": $.fn.dataTable.render.ellipsis(60, true),
},
{
"targets": [3],

View file

@ -255,11 +255,11 @@
},
{
"targets": [3],
"render": $.fn.dataTable.render.ellipsis(30, true),
"render": $.fn.dataTable.render.ellipsis(40, true),
},
{
"targets": [4],
"render": $.fn.dataTable.render.ellipsis(40, true),
"render": $.fn.dataTable.render.ellipsis(70, true),
}
],
"scrollX": false,