fusefrontend: move hole padding check out of Write()

The details of the hole handling don't have to be in
Write, so move it away.
This commit is contained in:
Jakob Unterwurzacher 2016-10-25 22:37:45 +02:00
parent 6538dc15af
commit d64ccf7cf4
2 changed files with 29 additions and 21 deletions

View File

@ -297,21 +297,11 @@ func (f *file) Write(data []byte, off int64) (uint32, fuse.Status) {
}
wlock.lock(f.ino)
defer wlock.unlock(f.ino)
tlog.Debug.Printf("ino%d: FUSE Write: offset=%d length=%d", f.ino, off, len(data))
fi, err := f.fd.Stat()
if err != nil {
tlog.Warn.Printf("Write: Fstat failed: %v", err)
return 0, fuse.ToStatus(err)
}
plainSize := f.contentEnc.CipherSizeToPlainSize(uint64(fi.Size()))
if f.createsCiphertextHole(plainSize, off) {
status := f.zeroPad(plainSize)
if status != fuse.OK {
tlog.Warn.Printf("zeroPad returned error %v", status)
return 0, status
}
// If the write creates a file hole, we have to zero-pad the last block.
status := f.writePadHole(off)
if !status.Ok() {
return 0, status
}
return f.doWrite(data, off)
}

View File

@ -8,17 +8,35 @@ import (
"github.com/rfjakob/gocryptfs/internal/tlog"
)
// Will a write to plaintext offset "off" create a file hole in the ciphertext?
func (f *file) createsCiphertextHole(plainSize uint64, off int64) bool {
// Will a write to plaintext offset "targetOff" create a file hole in the
// ciphertext? If yes, zero-pad the last ciphertext block.
func (f *file) writePadHole(targetOff int64) fuse.Status {
// Get the current file size.
fi, err := f.fd.Stat()
if err != nil {
tlog.Warn.Printf("checkAndPadHole: Fstat failed: %v", err)
return fuse.ToStatus(err)
}
plainSize := f.contentEnc.CipherSizeToPlainSize(uint64(fi.Size()))
// Appending a single byte to the file (equivalent to writing to
// offset=plainSize) would write to "nextBlock".
nextBlock := f.contentEnc.PlainOffToBlockNo(plainSize)
// targetBlock is the block the user wants to write to.
targetBlock := f.contentEnc.PlainOffToBlockNo(uint64(off))
// If the write goes past the next block, nextBlock will have
// to be zero-padded to the block boundary and at least nextBlock+1
// becomes a file hole in the ciphertext.
return targetBlock > nextBlock
targetBlock := f.contentEnc.PlainOffToBlockNo(uint64(targetOff))
// The write goes into an existing block or (if the last block was full)
// starts a new one directly after the last block. Nothing to do.
if targetBlock <= nextBlock {
return fuse.OK
}
// The write goes past the next block. nextBlock has
// to be zero-padded to the block boundary and (at least) nextBlock+1
// will become a file hole in the ciphertext.
status := f.zeroPad(plainSize)
if status != fuse.OK {
tlog.Warn.Printf("zeroPad returned error %v", status)
return status
}
return fuse.OK
}
// Zero-pad the file of size plainSize to the next block boundary