diff options
author | Jakob Unterwurzacher | 2020-07-23 22:55:07 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2020-07-23 22:55:07 +0200 |
commit | 9cd24d79a2a5499eefc3403516eba9d9fcbf1079 (patch) | |
tree | ffb6551b91e1fc614eff04ebaede6143a1cf2a5b /internal/fusefrontend/file2_holes.go | |
parent | 8915785acf7e6e7908b32103406620f243093931 (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.go | 40 |
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 } |