Zero-pad last block if a file hole is created on Write()
Fixes TestFileHoles test
This commit is contained in:
parent
5229b8f5f5
commit
2003ca965d
@ -113,7 +113,7 @@ func (f *file) doRead(off uint64, length uint64) ([]byte, fuse.Status) {
|
|||||||
|
|
||||||
// Read - FUSE call
|
// Read - FUSE call
|
||||||
func (f *file) Read(buf []byte, off int64) (resultData fuse.ReadResult, code fuse.Status) {
|
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 {
|
if f.writeOnly {
|
||||||
cryptfs.Warn.Printf("ino%d: Tried to read from write-only file\n", f.ino)
|
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
|
return fuse.ReadResultData(out), status
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write - FUSE call
|
// Do the actual write
|
||||||
func (f *file) Write(data []byte, off int64) (uint32, fuse.Status) {
|
func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) {
|
||||||
cryptfs.Debug.Printf("ino%d: Write %s: offset=%d length=%d\n", f.ino, off, len(data))
|
|
||||||
|
|
||||||
var written uint32
|
var written uint32
|
||||||
status := fuse.OK
|
status := fuse.OK
|
||||||
dataBuf := bytes.NewBuffer(data)
|
dataBuf := bytes.NewBuffer(data)
|
||||||
@ -177,10 +175,16 @@ func (f *file) Write(data []byte, off int64) (uint32, fuse.Status) {
|
|||||||
}
|
}
|
||||||
written += uint32(b.Length)
|
written += uint32(b.Length)
|
||||||
}
|
}
|
||||||
|
|
||||||
return written, status
|
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
|
// Release - FUSE call, forget file
|
||||||
func (f *file) Release() {
|
func (f *file) Release() {
|
||||||
f.lock.Lock()
|
f.lock.Lock()
|
||||||
|
38
pathfs_frontend/file_holes.go
Normal file
38
pathfs_frontend/file_holes.go
Normal 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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user