diff options
author | Jakob Unterwurzacher | 2020-08-09 22:11:46 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2020-08-09 22:11:46 +0200 |
commit | 6d4f1a6888cafd218cb97bd11de6a7553d9bc8f1 (patch) | |
tree | 7b48b6e97c4c73a4e0e9dce3456768526c46da65 /internal/fusefrontend_reverse/file.go | |
parent | 527609266386890fe1657c225c643ca448bcd71d (diff) |
v2api/reverse: implement Read
Diffstat (limited to 'internal/fusefrontend_reverse/file.go')
-rw-r--r-- | internal/fusefrontend_reverse/file.go | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/internal/fusefrontend_reverse/file.go b/internal/fusefrontend_reverse/file.go new file mode 100644 index 0000000..55f5f80 --- /dev/null +++ b/internal/fusefrontend_reverse/file.go @@ -0,0 +1,70 @@ +package fusefrontend_reverse + +import ( + "bytes" + "context" + "os" + "syscall" + + "github.com/hanwen/go-fuse/v2/fs" + "github.com/hanwen/go-fuse/v2/fuse" + + "github.com/rfjakob/gocryptfs/internal/contentenc" +) + +type File struct { + // Backing FD + fd *os.File + // File header (contains the IV) + header contentenc.FileHeader + // IV for block 0 + block0IV []byte + // Content encryption helper + contentEnc *contentenc.ContentEnc +} + +// Read - FUSE call +func (f *File) Read(ctx context.Context, buf []byte, ioff int64) (resultData fuse.ReadResult, errno syscall.Errno) { + length := uint64(len(buf)) + off := uint64(ioff) + out := bytes.NewBuffer(buf[:0]) + var header []byte + + // Synthesize file header + if off < contentenc.HeaderLen { + header = f.header.Pack() + // Truncate to requested part + end := int(off) + len(buf) + if end > len(header) { + end = len(header) + } + header = header[off:end] + // Write into output buffer and adjust offsets + out.Write(header) + hLen := uint64(len(header)) + off += hLen + length -= hLen + } + + // Read actual file data + if length > 0 { + fileData, err := f.readBackingFile(off, length) + if err != nil { + return nil, fs.ToErrno(err) + } + if len(fileData) == 0 { + // If we could not read any actual data, we also don't want to + // return the file header. An empty file stays empty in encrypted + // form. + return nil, 0 + } + out.Write(fileData) + } + + return fuse.ReadResultData(out.Bytes()), 0 +} + +// Release - FUSE call, close file +func (f *File) Release(context.Context) syscall.Errno { + return fs.ToErrno(f.fd.Close()) +} |