From 902babdf22199d73171716e643f1ffbb65e6fb48 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Sun, 1 Nov 2015 12:11:36 +0100 Subject: Refactor ciphertext <-> plaintext offset translation functions Move all the intelligence into the new file address_translation.go. That the calculations were spread out too much became apparent when adding the file header. This should make the code much easier to modify in the future. --- pathfs_frontend/file.go | 50 +++++++++++++++++++++---------------------- pathfs_frontend/file_holes.go | 4 ++-- pathfs_frontend/fs.go | 2 +- 3 files changed, 27 insertions(+), 29 deletions(-) (limited to 'pathfs_frontend') diff --git a/pathfs_frontend/file.go b/pathfs_frontend/file.go index 438fe77..e8d7003 100644 --- a/pathfs_frontend/file.go +++ b/pathfs_frontend/file.go @@ -128,8 +128,10 @@ func (f *file) doRead(off uint64, length uint64) ([]byte, fuse.Status) { } // Read the backing ciphertext in one go - alignedOffset, alignedLength, skip := f.cfs.CiphertextRange(off, length) - cryptfs.Debug.Printf("CiphertextRange(%d, %d) -> %d, %d, %d\n", off, length, alignedOffset, alignedLength, skip) + blocks := f.cfs.ExplodePlainRange(off, length) + alignedOffset, alignedLength := blocks[0].JointCiphertextRange(blocks) + skip := blocks[0].Skip + cryptfs.Debug.Printf("JointCiphertextRange(%d, %d) -> %d, %d, %d\n", off, length, alignedOffset, alignedLength, skip) ciphertext := make([]byte, int(alignedLength)) f.fdLock.Lock() n, err := f.fd.ReadAt(ciphertext, int64(alignedOffset)) @@ -141,27 +143,27 @@ func (f *file) doRead(off uint64, length uint64) ([]byte, fuse.Status) { // Truncate ciphertext buffer down to actually read bytes ciphertext = ciphertext[0:n] - blockNo := (alignedOffset - cryptfs.HEADER_LEN) / f.cfs.CipherBS() - cryptfs.Debug.Printf("ReadAt offset=%d bytes (%d blocks), want=%d, got=%d\n", alignedOffset, blockNo, alignedLength, n) + firstBlockNo := blocks[0].BlockNo + cryptfs.Debug.Printf("ReadAt offset=%d bytes (%d blocks), want=%d, got=%d\n", alignedOffset, firstBlockNo, alignedLength, n) // Decrypt it - plaintext, err := f.cfs.DecryptBlocks(ciphertext, blockNo, f.header.Id) + plaintext, err := f.cfs.DecryptBlocks(ciphertext, firstBlockNo, f.header.Id) if err != nil { - blockNo := (alignedOffset + uint64(len(plaintext))) / f.cfs.PlainBS() - cipherOff := cryptfs.HEADER_LEN + blockNo * f.cfs.CipherBS() - plainOff := blockNo * f.cfs.PlainBS() - cryptfs.Warn.Printf("ino%d: doRead: corrupt block #%d (plainOff=%d/%d, cipherOff=%d/%d)\n", - f.ino, blockNo, plainOff, f.cfs.PlainBS(), cipherOff, f.cfs.CipherBS()) + curruptBlockNo := firstBlockNo + f.cfs.PlainOffToBlockNo(uint64(len(plaintext))) + cipherOff := f.cfs.BlockNoToCipherOff(curruptBlockNo) + plainOff := f.cfs.BlockNoToPlainOff(curruptBlockNo) + cryptfs.Warn.Printf("ino%d: doRead: corrupt block #%d (plainOff=%d, cipherOff=%d)\n", + f.ino, curruptBlockNo, plainOff, cipherOff) return nil, fuse.EIO } // Crop down to the relevant part var out []byte lenHave := len(plaintext) - lenWant := skip + int(length) + lenWant := int(skip + length) if lenHave > lenWant { - out = plaintext[skip : skip+int(length)] - } else if lenHave > skip { + out = plaintext[skip:lenWant] + } else if lenHave > int(skip) { out = plaintext[skip:lenHave] } // else: out stays empty, file was smaller than the requested offset @@ -216,7 +218,7 @@ func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) { var written uint32 status := fuse.OK dataBuf := bytes.NewBuffer(data) - blocks := f.cfs.SplitRange(uint64(off), uint64(len(data))) + blocks := f.cfs.ExplodePlainRange(uint64(off), uint64(len(data))) for _, b := range blocks { blockData := dataBuf.Next(int(b.Length)) @@ -239,11 +241,7 @@ func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) { blockOffset, _ := b.CiphertextRange() blockData = f.cfs.EncryptBlock(blockData, b.BlockNo, f.header.Id) cryptfs.Debug.Printf("ino%d: Writing %d bytes to block #%d, md5=%s\n", - f.ino, len(blockData) - cryptfs.BLOCK_OVERHEAD, b.BlockNo, cryptfs.Debug.Md5sum(blockData)) - if len(blockData) != int(f.cfs.CipherBS()) { - cryptfs.Debug.Printf("ino%d: Writing partial block #%d (%d bytes)\n", - f.ino, b.BlockNo, len(blockData) - cryptfs.BLOCK_OVERHEAD) - } + f.ino, len(blockData)-cryptfs.BLOCK_OVERHEAD, b.BlockNo, cryptfs.Debug.Md5sum(blockData)) f.fdLock.Lock() _, err := f.fd.WriteAt(blockData, int64(blockOffset)) f.fdLock.Unlock() @@ -267,7 +265,7 @@ func (f *file) Write(data []byte, off int64) (uint32, fuse.Status) { cryptfs.Warn.Printf("Write: Fstat failed: %v\n", err) return 0, fuse.ToStatus(err) } - plainSize := f.cfs.PlainSize(uint64(fi.Size())) + plainSize := f.cfs.CipherSizeToPlainSize(uint64(fi.Size())) if f.createsHole(plainSize, off) { status := f.zeroPad(plainSize) if status != fuse.OK { @@ -332,7 +330,7 @@ func (f *file) Truncate(newSize uint64) fuse.Status { cryptfs.Warn.Printf("Truncate: Fstat failed: %v\n", err) return fuse.ToStatus(err) } - oldSize := f.cfs.PlainSize(uint64(fi.Size())) + oldSize := f.cfs.CipherSizeToPlainSize(uint64(fi.Size())) { oldB := float32(oldSize) / float32(f.cfs.PlainBS()) newB := float32(newSize) / float32(f.cfs.PlainBS()) @@ -350,7 +348,7 @@ func (f *file) Truncate(newSize uint64) fuse.Status { } } - blocks := f.cfs.SplitRange(oldSize, newSize-oldSize) + blocks := f.cfs.ExplodePlainRange(oldSize, newSize-oldSize) for _, b := range blocks { // First and last block may be partial if b.IsPartial() { @@ -374,9 +372,9 @@ func (f *file) Truncate(newSize uint64) fuse.Status { return fuse.OK } else { // File shrinks - blockNo := f.cfs.BlockNoPlainOff(newSize) - cipherOff := cryptfs.HEADER_LEN + blockNo * f.cfs.CipherBS() - plainOff := blockNo * f.cfs.PlainBS() + blockNo := f.cfs.PlainOffToBlockNo(newSize) + cipherOff := f.cfs.BlockNoToCipherOff(blockNo) + plainOff := f.cfs.BlockNoToPlainOff(blockNo) lastBlockLen := newSize - plainOff var data []byte if lastBlockLen > 0 { @@ -430,7 +428,7 @@ func (f *file) GetAttr(a *fuse.Attr) fuse.Status { return fuse.ToStatus(err) } a.FromStat(&st) - a.Size = f.cfs.PlainSize(a.Size) + a.Size = f.cfs.CipherSizeToPlainSize(a.Size) return fuse.OK } diff --git a/pathfs_frontend/file_holes.go b/pathfs_frontend/file_holes.go index f906aa6..3db4828 100644 --- a/pathfs_frontend/file_holes.go +++ b/pathfs_frontend/file_holes.go @@ -7,8 +7,8 @@ import ( // Will a write to offset "off" create a file hole? func (f *file) createsHole(plainSize uint64, off int64) bool { - nextBlock := f.cfs.BlockNoPlainOff(plainSize) - targetBlock := f.cfs.BlockNoPlainOff(uint64(off)) + nextBlock := f.cfs.PlainOffToBlockNo(plainSize) + targetBlock := f.cfs.PlainOffToBlockNo(uint64(off)) if targetBlock > nextBlock { return true } diff --git a/pathfs_frontend/fs.go b/pathfs_frontend/fs.go index eebc87b..3ec503f 100644 --- a/pathfs_frontend/fs.go +++ b/pathfs_frontend/fs.go @@ -41,7 +41,7 @@ func (fs *FS) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Stat return a, status } if a.IsRegular() { - a.Size = fs.PlainSize(a.Size) + a.Size = fs.CipherSizeToPlainSize(a.Size) } else if a.IsSymlink() { target, _ := fs.Readlink(name, context) a.Size = uint64(len(target)) -- cgit v1.2.3