Browse Source

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

Simon Frei 4 years ago
parent
commit
708a5c2070
2 changed files with 39 additions and 11 deletions
  1. 20 0
      lib/model/folder_sendrecv.go
  2. 19 11
      lib/model/sharedpullerstate.go

+ 20 - 0
lib/model/folder_sendrecv.go

@@ -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}
 }
 

+ 19 - 11
lib/model/sharedpullerstate.go

@@ -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 {
+	if s.writer == nil {
+		if err := s.addWriterLocked(); 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 := s.file
+	wireFile := file
 	wireFile.Name = osutil.NormalizedFilename(wireFile.Name)
 
-	bs := make([]byte, encryptionTrailerSize(wireFile))
+	trailerSize := encryptionTrailerSize(wireFile)
+	bs := make([]byte, trailerSize)
 	n, err := wireFile.MarshalTo(bs)
 	if err != nil {
-		return err
+		return 0, 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
+	if _, err := writer.WriteAt(bs, wireFile.Size); err != nil {
+		return 0, err
 	}
 
-	return nil
+	return trailerSize, nil
 }
 
 func encryptionTrailerSize(file protocol.FileInfo) int64 {