Zero-pad last block if a file hole is created on Write()

Fixes TestFileHoles test
This commit is contained in:
Jakob Unterwurzacher 2015-10-04 11:39:35 +02:00
parent 5229b8f5f5
commit 2003ca965d
2 changed files with 48 additions and 6 deletions

View File

@ -113,7 +113,7 @@ func (f *file) doRead(off uint64, length uint64) ([]byte, fuse.Status) {
// Read - FUSE call
func (f *file) Read(buf []byte, off int64) (resultData fuse.ReadResult, code fuse.Status) {
cryptfs.Debug.Printf("ino%d: Read: offset=%d length=%d\n", f.ino, len(buf), off)
cryptfs.Debug.Printf("ino%d: FUSE Read: offset=%d length=%d\n", f.ino, len(buf), off)
if f.writeOnly {
cryptfs.Warn.Printf("ino%d: Tried to read from write-only file\n", f.ino)
@ -133,10 +133,8 @@ func (f *file) Read(buf []byte, off int64) (resultData fuse.ReadResult, code fus
return fuse.ReadResultData(out), status
}
// Write - FUSE call
func (f *file) Write(data []byte, off int64) (uint32, fuse.Status) {
cryptfs.Debug.Printf("ino%d: Write %s: offset=%d length=%d\n", f.ino, off, len(data))
// Do the actual write
func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) {
var written uint32
status := fuse.OK
dataBuf := bytes.NewBuffer(data)
@ -177,10 +175,16 @@ func (f *file) Write(data []byte, off int64) (uint32, fuse.Status) {
}
written += uint32(b.Length)
}
return written, status
}
// Write - FUSE call
func (f *file) Write(data []byte, off int64) (uint32, fuse.Status) {
cryptfs.Debug.Printf("ino%d: FUSE Write %s: offset=%d length=%d\n", f.ino, off, len(data))
f.conditionalZeroPad(off)
return f.doWrite(data, off)
}
// Release - FUSE call, forget file
func (f *file) Release() {
f.lock.Lock()

View File

@ -0,0 +1,38 @@
package pathfs_frontend
import (
"fmt"
"github.com/hanwen/go-fuse/fuse"
"github.com/rfjakob/gocryptfs/cryptfs"
)
// Will a write to offset "off" create a file hole?
func (f *file) createsHole(cipherSize uint64, off int64) bool {
nextBlock := f.cfs.BlockNoCipherOff(cipherSize)
targetBlock := f.cfs.BlockNoPlainOff(uint64(off))
if targetBlock > nextBlock {
return true
}
return false
}
// Zero-pad the file if a write to "off" creates a file hole
func (f *file) conditionalZeroPad(off int64) fuse.Status {
fi, err := f.fd.Stat()
if err != nil {
cryptfs.Warn.Printf("conditionalZeroPad: Stat: %v\n", err)
return fuse.ToStatus(err)
}
cipherSize := uint64(fi.Size())
if f.createsHole(cipherSize, off) == false {
return fuse.OK
}
plainSize := f.cfs.PlainSize(cipherSize)
lastBlockLen := plainSize % f.cfs.PlainBS()
missing := f.cfs.PlainBS() - lastBlockLen
pad := make([]byte, missing)
_, status := f.doWrite(pad, int64(plainSize))
return status
}