lib/model: Write trailer when shortcutting on recv-enc (fixes #7991) (#7992)

This commit is contained in:
Simon Frei 2021-10-05 11:23:27 +02:00 committed by GitHub
parent 92eaf52c21
commit 708a5c2070
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 16 deletions

View File

@ -1229,6 +1229,26 @@ func (f *sendReceiveFolder) shortcutFile(file protocol.FileInfo, dbUpdateChan ch
f.mtimefs.Chtimes(file.Name, file.ModTime(), file.ModTime()) // never fails
// Still need to re-write the trailer with the new encrypted fileinfo.
if f.Type == config.FolderTypeReceiveEncrypted {
err = inWritableDir(func(path string) error {
fd, err := f.mtimefs.OpenFile(path, fs.OptReadWrite, 0666)
if err != nil {
return err
}
defer fd.Close()
trailerSize, err := writeEncryptionTrailer(file, fd)
if err != nil {
return err
}
return fd.Truncate(file.Size + trailerSize)
}, f.mtimefs, file.Name, true)
if err != nil {
f.newPullError(file.Name, err)
return
}
}
dbUpdateChan <- dbUpdateJob{file, dbUpdateShortcutFile}
}

View File

@ -8,6 +8,7 @@ package model
import (
"encoding/binary"
"io"
"time"
"github.com/pkg/errors"
@ -347,29 +348,36 @@ func (s *sharedPullerState) finalClose() (bool, error) {
// folder from encrypted data we can extract this FileInfo from the end of
// the file and regain the original metadata.
func (s *sharedPullerState) finalizeEncrypted() error {
// Here the file is in native format, while encryption happens in
// wire format (always slashes).
wireFile := s.file
wireFile.Name = osutil.NormalizedFilename(wireFile.Name)
bs := make([]byte, encryptionTrailerSize(wireFile))
n, err := wireFile.MarshalTo(bs)
if err != nil {
return err
}
binary.BigEndian.PutUint32(bs[n:], uint32(n))
bs = bs[:n+4]
if s.writer == nil {
if err := s.addWriterLocked(); err != nil {
return err
}
}
if _, err := s.writer.WriteAt(bs, wireFile.Size); err != nil {
return err
_, err := writeEncryptionTrailer(s.file, s.writer)
return err
}
// Returns the size of the written trailer.
func writeEncryptionTrailer(file protocol.FileInfo, writer io.WriterAt) (int64, error) {
// Here the file is in native format, while encryption happens in
// wire format (always slashes).
wireFile := file
wireFile.Name = osutil.NormalizedFilename(wireFile.Name)
trailerSize := encryptionTrailerSize(wireFile)
bs := make([]byte, trailerSize)
n, err := wireFile.MarshalTo(bs)
if err != nil {
return 0, err
}
binary.BigEndian.PutUint32(bs[n:], uint32(n))
bs = bs[:n+4]
if _, err := writer.WriteAt(bs, wireFile.Size); err != nil {
return 0, err
}
return nil
return trailerSize, nil
}
func encryptionTrailerSize(file protocol.FileInfo) int64 {