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 | |
| parent | 8915785acf7e6e7908b32103406620f243093931 (diff) | |
v2api: implement Lseek
This also fixes the last remaining tests/fsck failure.
| -rw-r--r-- | internal/fusefrontend/file2_api_check.go | 2 | ||||
| -rw-r--r-- | internal/fusefrontend/file2_holes.go | 40 | ||||
| -rw-r--r-- | tests/defaults/main_test.go | 32 | 
3 files changed, 41 insertions, 33 deletions
| diff --git a/internal/fusefrontend/file2_api_check.go b/internal/fusefrontend/file2_api_check.go index 4a6d6a1..01f9a46 100644 --- a/internal/fusefrontend/file2_api_check.go +++ b/internal/fusefrontend/file2_api_check.go @@ -13,11 +13,11 @@ var _ = (fs.FileWriter)((*File2)(nil))  var _ = (fs.FileFsyncer)((*File2)(nil))  var _ = (fs.FileFlusher)((*File2)(nil))  var _ = (fs.FileAllocater)((*File2)(nil)) +var _ = (fs.FileLseeker)((*File2)(nil))  /* TODO  var _ = (fs.FileHandle)((*File2)(nil))  var _ = (fs.FileGetlker)((*File2)(nil))  var _ = (fs.FileSetlker)((*File2)(nil))  var _ = (fs.FileSetlkwer)((*File2)(nil)) -var _ = (fs.FileLseeker)((*File2)(nil))  */ 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  } diff --git a/tests/defaults/main_test.go b/tests/defaults/main_test.go index 51f5cd2..f59ea38 100644 --- a/tests/defaults/main_test.go +++ b/tests/defaults/main_test.go @@ -7,6 +7,7 @@ import (  	"io/ioutil"  	"os"  	"os/exec" +	"path/filepath"  	"runtime"  	"strings"  	"sync" @@ -261,3 +262,34 @@ func TestCpWarnings(t *testing.T) {  		t.Fatalf("Got warnings from cp -a:\n%s", string(out))  	}  } + +func TestSeekData(t *testing.T) { +	fn := filepath.Join(test_helpers.DefaultPlainDir, t.Name()) +	f, err := os.Create(fn) +	if err != nil { +		t.Fatal(err) +	} +	var oneTiB int64 = 1024 * 1024 * 1024 * 1024 +	if _, err = f.Seek(oneTiB, 0); err != nil { +		t.Fatal(err) +	} +	if _, err = f.Write([]byte("foo")); err != nil { +		t.Fatal(err) +	} +	f.Close() + +	const SEEK_DATA = 3 + +	f, err = os.Open(fn) +	if err != nil { +		t.Fatal(err) +	} +	off, err := f.Seek(1024*1024, SEEK_DATA) +	if err != nil { +		t.Fatal(err) +	} +	if off < oneTiB-1024*1024 { +		t.Errorf("off=%d, expected=%d\n", off, oneTiB) +	} +	f.Close() +} | 
