aboutsummaryrefslogtreecommitdiff
path: root/internal/fusefrontend_reverse/file_helpers.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2020-08-09 22:11:46 +0200
committerJakob Unterwurzacher2020-08-09 22:11:46 +0200
commit6d4f1a6888cafd218cb97bd11de6a7553d9bc8f1 (patch)
tree7b48b6e97c4c73a4e0e9dce3456768526c46da65 /internal/fusefrontend_reverse/file_helpers.go
parent527609266386890fe1657c225c643ca448bcd71d (diff)
v2api/reverse: implement Read
Diffstat (limited to 'internal/fusefrontend_reverse/file_helpers.go')
-rw-r--r--internal/fusefrontend_reverse/file_helpers.go62
1 files changed, 62 insertions, 0 deletions
diff --git a/internal/fusefrontend_reverse/file_helpers.go b/internal/fusefrontend_reverse/file_helpers.go
new file mode 100644
index 0000000..f024e69
--- /dev/null
+++ b/internal/fusefrontend_reverse/file_helpers.go
@@ -0,0 +1,62 @@
+package fusefrontend_reverse
+
+import (
+ "bytes"
+ "io"
+ "sync"
+
+ "github.com/rfjakob/gocryptfs/internal/contentenc"
+ "github.com/rfjakob/gocryptfs/internal/pathiv"
+ "github.com/rfjakob/gocryptfs/internal/tlog"
+)
+
+var inodeTable sync.Map
+
+// encryptBlocks - encrypt "plaintext" into a number of ciphertext blocks.
+// "plaintext" must already be block-aligned.
+func (rf *File) encryptBlocks(plaintext []byte, firstBlockNo uint64, fileID []byte, block0IV []byte) []byte {
+ inBuf := bytes.NewBuffer(plaintext)
+ var outBuf bytes.Buffer
+ bs := int(rf.contentEnc.PlainBS())
+ for blockNo := firstBlockNo; inBuf.Len() > 0; blockNo++ {
+ inBlock := inBuf.Next(bs)
+ iv := pathiv.BlockIV(block0IV, blockNo)
+ outBlock := rf.contentEnc.EncryptBlockNonce(inBlock, blockNo, fileID, iv)
+ outBuf.Write(outBlock)
+ }
+ return outBuf.Bytes()
+}
+
+// readBackingFile: read from the backing plaintext file, encrypt it, return the
+// ciphertext.
+// "off" ... ciphertext offset (must be >= HEADER_LEN)
+// "length" ... ciphertext length
+func (f *File) readBackingFile(off uint64, length uint64) (out []byte, err error) {
+ blocks := f.contentEnc.ExplodeCipherRange(off, length)
+
+ // Read the backing plaintext in one go
+ alignedOffset, alignedLength := contentenc.JointPlaintextRange(blocks)
+ plaintext := make([]byte, int(alignedLength))
+ n, err := f.fd.ReadAt(plaintext, int64(alignedOffset))
+ if err != nil && err != io.EOF {
+ tlog.Warn.Printf("readBackingFile: ReadAt: %s", err.Error())
+ return nil, err
+ }
+ // Truncate buffer down to actually read bytes
+ plaintext = plaintext[0:n]
+
+ // Encrypt blocks
+ ciphertext := f.encryptBlocks(plaintext, blocks[0].BlockNo, f.header.ID, f.block0IV)
+
+ // Crop down to the relevant part
+ lenHave := len(ciphertext)
+ skip := blocks[0].Skip
+ endWant := int(skip + length)
+ if lenHave > endWant {
+ out = ciphertext[skip:endWant]
+ } else if lenHave > int(skip) {
+ out = ciphertext[skip:lenHave]
+ } // else: out stays empty, file was smaller than the requested offset
+
+ return out, nil
+}