summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pathfs_frontend/file.go16
-rw-r--r--pathfs_frontend/file_holes.go38
2 files changed, 48 insertions, 6 deletions
diff --git a/pathfs_frontend/file.go b/pathfs_frontend/file.go
index 9c58557..2c2f1eb 100644
--- a/pathfs_frontend/file.go
+++ b/pathfs_frontend/file.go
@@ -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()
diff --git a/pathfs_frontend/file_holes.go b/pathfs_frontend/file_holes.go
new file mode 100644
index 0000000..8c9c83f
--- /dev/null
+++ b/pathfs_frontend/file_holes.go
@@ -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
+}