diff options
| author | Jakob Unterwurzacher | 2016-10-25 22:37:45 +0200 | 
|---|---|---|
| committer | Jakob Unterwurzacher | 2016-10-25 22:37:45 +0200 | 
| commit | d64ccf7cf4d110d515b07b7f95127f12ecd4d318 (patch) | |
| tree | 948bd0615bd80a028d4ec38640fa4e5680d50dd9 /internal/fusefrontend | |
| parent | 6538dc15afb7a7a159f070a57a1e9073ca076661 (diff) | |
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.
Diffstat (limited to 'internal/fusefrontend')
| -rw-r--r-- | internal/fusefrontend/file.go | 18 | ||||
| -rw-r--r-- | internal/fusefrontend/file_holes.go | 32 | 
2 files changed, 29 insertions, 21 deletions
| diff --git a/internal/fusefrontend/file.go b/internal/fusefrontend/file.go index 9fb9f7e..ee48930 100644 --- a/internal/fusefrontend/file.go +++ b/internal/fusefrontend/file.go @@ -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)  } diff --git a/internal/fusefrontend/file_holes.go b/internal/fusefrontend/file_holes.go index ff626d1..5b7a244 100644 --- a/internal/fusefrontend/file_holes.go +++ b/internal/fusefrontend/file_holes.go @@ -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 | 
