summaryrefslogtreecommitdiff
path: root/internal/fusefrontend/file2_holes.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2020-07-23 22:55:07 +0200
committerJakob Unterwurzacher2020-07-23 22:55:07 +0200
commit9cd24d79a2a5499eefc3403516eba9d9fcbf1079 (patch)
treeffb6551b91e1fc614eff04ebaede6143a1cf2a5b /internal/fusefrontend/file2_holes.go
parent8915785acf7e6e7908b32103406620f243093931 (diff)
v2api: implement Lseek
This also fixes the last remaining tests/fsck failure.
Diffstat (limited to 'internal/fusefrontend/file2_holes.go')
-rw-r--r--internal/fusefrontend/file2_holes.go40
1 files changed, 8 insertions, 32 deletions
diff --git a/internal/fusefrontend/file2_holes.go b/internal/fusefrontend/file2_holes.go
index 83918d2..5c314d3 100644
--- a/internal/fusefrontend/file2_holes.go
+++ b/internal/fusefrontend/file2_holes.go
@@ -3,7 +3,7 @@ package fusefrontend
// Helper functions for sparse files (files with holes)
import (
- "runtime"
+ "context"
"syscall"
"github.com/hanwen/go-fuse/v2/fs"
@@ -56,37 +56,13 @@ func (f *File2) zeroPad(plainSize uint64) syscall.Errno {
return errno
}
-// SeekData calls the lseek syscall with SEEK_DATA. It returns the offset of the
-// next data bytes, skipping over file holes.
-func (f *File2) SeekData(oldOffset int64) (int64, error) {
- if runtime.GOOS != "linux" {
- // Does MacOS support something like this?
- return 0, syscall.EOPNOTSUPP
- }
- const SEEK_DATA = 3
-
- // Convert plaintext offset to ciphertext offset and round down to the
- // start of the current block. File holes smaller than a full block will
- // be ignored.
- blockNo := f.contentEnc.PlainOffToBlockNo(uint64(oldOffset))
- oldCipherOff := int64(f.contentEnc.BlockNoToCipherOff(blockNo))
-
- // Determine the next data offset. If the old offset points to (or beyond)
- // the end of the file, the Seek syscall fails with syscall.ENXIO.
- newCipherOff, err := syscall.Seek(f.intFd(), oldCipherOff, SEEK_DATA)
+// Lseek - FUSE call.
+func (f *File2) Lseek(ctx context.Context, off uint64, whence uint32) (uint64, syscall.Errno) {
+ cipherOff := f.rootNode.contentEnc.PlainSizeToCipherSize(off)
+ newCipherOff, err := syscall.Seek(f.intFd(), int64(cipherOff), int(whence))
if err != nil {
- return 0, err
+ return uint64(newCipherOff), fs.ToErrno(err)
}
-
- // Convert ciphertext offset back to plaintext offset. At this point,
- // newCipherOff should always be >= contentenc.HeaderLen. Round down,
- // but ensure that the result is never smaller than the initial offset
- // (to avoid endless loops).
- blockNo = f.contentEnc.CipherOffToBlockNo(uint64(newCipherOff))
- newOffset := int64(f.contentEnc.BlockNoToPlainOff(blockNo))
- if newOffset < oldOffset {
- newOffset = oldOffset
- }
-
- return newOffset, nil
+ newOff := f.contentEnc.CipherSizeToPlainSize(uint64(newCipherOff))
+ return newOff, 0
}