aboutsummaryrefslogtreecommitdiff
path: root/internal/fusefrontend_reverse/file.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2020-08-09 22:11:46 +0200
committerJakob Unterwurzacher2020-08-09 22:11:46 +0200
commit6d4f1a6888cafd218cb97bd11de6a7553d9bc8f1 (patch)
tree7b48b6e97c4c73a4e0e9dce3456768526c46da65 /internal/fusefrontend_reverse/file.go
parent527609266386890fe1657c225c643ca448bcd71d (diff)
v2api/reverse: implement Read
Diffstat (limited to 'internal/fusefrontend_reverse/file.go')
-rw-r--r--internal/fusefrontend_reverse/file.go70
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())
+}