From caaad7c8d7261b944931e9baf94568aa8c12c8bf Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Tue, 8 Sep 2015 21:35:06 +0200 Subject: [PATCH] Add pathfs frontend, part II Fix issues in read and write paths. Now passes selftest. --- cryptfs/log.go | 2 +- pathfs_frontend/file.go | 51 ++++++++++++++++++++++++++--------------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/cryptfs/log.go b/cryptfs/log.go index 8233529..f9c46c8 100644 --- a/cryptfs/log.go +++ b/cryptfs/log.go @@ -15,5 +15,5 @@ func (l logChannel) Printf(format string, args ...interface{}) { } -var Debug = logChannel{true} +var Debug = logChannel{false} var Warn = logChannel{true} diff --git a/pathfs_frontend/file.go b/pathfs_frontend/file.go index 8b6d61d..0ce4257 100644 --- a/pathfs_frontend/file.go +++ b/pathfs_frontend/file.go @@ -51,44 +51,58 @@ func (f *file) String() string { return fmt.Sprintf("cryptFile(%s)", f.fd.Name()) } -// Read - FUSE call -func (f *file) Read(buf []byte, off int64) (resultData fuse.ReadResult, code fuse.Status) { - cryptfs.Debug.Printf("\n\nGot read request: len=%d off=%d\n", len(buf), off) - - if f.writeOnly { - return nil, fuse.EBADF - } +// Called by Read() and for RMW in Write() +func (f *file) doRead(off uint64, length uint64) ([]byte, fuse.Status) { // Read the backing ciphertext in one go - alignedOffset, alignedLength, skip := f.cfs.CiphertextRange(uint64(off), uint64(len(buf))) + alignedOffset, alignedLength, skip := f.cfs.CiphertextRange(off, length) ciphertext := make([]byte, int(alignedLength)) - _, err := f.fd.ReadAt(ciphertext, int64(alignedOffset)) + n, err := f.fd.ReadAt(ciphertext, int64(alignedOffset)) + ciphertext = ciphertext[0:n] + cryptfs.Debug.Printf("ReadAt length=%d offset=%d -> n=%d len=%d\n", alignedLength, alignedOffset, n, len(ciphertext)) if err != nil && err != io.EOF { - cryptfs.Warn.Printf("Read error: %s\n", err.Error()) + cryptfs.Warn.Printf("read: ReadAt: %s\n", err.Error()) return nil, fuse.ToStatus(err) } // Decrypt it plaintext, err := f.cfs.DecryptBlocks(ciphertext) if err != nil { - cryptfs.Warn.Printf("Decryption error: %s\n", err.Error()) + cryptfs.Warn.Printf("read: DecryptBlocks: %s\n", err.Error()) return nil, fuse.EIO } // Crop down to the relevant part var out []byte lenHave := len(plaintext) - lenWant := skip + len(buf) + lenWant := skip + int(length) if lenHave > lenWant { - out = plaintext[skip:skip + len(buf)] + out = plaintext[skip:skip + int(length)] } else if lenHave > skip { out = plaintext[skip:lenHave] + } else { + // Out stays empty, file was smaller than the requested offset } - // else: out stays empty - fmt.Printf("Read: returning %d bytes\n", len(plaintext)) + return out, fuse.OK +} - return fuse.ReadResultData(out), fuse.OK +// Read - FUSE call +func (f *file) Read(buf []byte, off int64) (resultData fuse.ReadResult, code fuse.Status) { + cryptfs.Debug.Printf("\n\nGot read request: len=%d off=%d\n", len(buf), off) + + if f.writeOnly { + cryptfs.Warn.Printf("Tried to read from write-only file\n") + return nil, fuse.EBADF + } + + out, status := f.doRead(uint64(off), uint64(len(buf))) + if status != fuse.OK { + return nil, status + } + + cryptfs.Debug.Printf("Read: returning %d bytes\n", len(out)) + return fuse.ReadResultData(out), status } // Write - FUSE call @@ -104,11 +118,10 @@ func (f *file) Write(data []byte, off int64) (uint32, fuse.Status) { // Incomplete block -> Read-Modify-Write if b.IsPartial() { // Read - oldData := make([]byte, f.cfs.PlainBS()) o, _ := b.PlaintextRange() - res, status := f.Read(oldData, int64(o)) - oldData, _ = res.Bytes(oldData) + oldData, status := f.doRead(f.cfs.PlainBS(), o) if status != fuse.OK { + cryptfs.Warn.Printf("RMW read failed: %s\n", status.String()) return written, status } // Modify