diff --git a/internal/fusefrontend_reverse/rfs.go b/internal/fusefrontend_reverse/rfs.go index f9a2979..a3a3d3b 100644 --- a/internal/fusefrontend_reverse/rfs.go +++ b/internal/fusefrontend_reverse/rfs.go @@ -221,6 +221,16 @@ func (rfs *ReverseFS) GetAttr(relPath string, context *fuse.Context) (*fuse.Attr // Calculate encrypted file size if a.IsRegular() { a.Size = rfs.contentEnc.PlainSizeToCipherSize(a.Size) + } else if a.IsSymlink() { + var linkTarget string + var readlinkStatus fuse.Status + + linkTarget, readlinkStatus = rfs.Readlink(relPath, context) + if !readlinkStatus.Ok() { + return nil, readlinkStatus + } + + a.Size = uint64(len(linkTarget)) } return a, fuse.OK } diff --git a/tests/reverse/correctness_test.go b/tests/reverse/correctness_test.go index db64983..bebf341 100644 --- a/tests/reverse/correctness_test.go +++ b/tests/reverse/correctness_test.go @@ -6,6 +6,7 @@ import ( "syscall" "testing" + "github.com/rfjakob/gocryptfs/internal/ctlsock" "github.com/rfjakob/gocryptfs/tests/test_helpers" ) @@ -51,6 +52,43 @@ func TestSymlinks(t *testing.T) { } } +// Symbolic link dentry sizes should be set to the length of the string +// that contains the target path. +func TestSymlinkDentrySize(t *testing.T) { + symlink := "a_symlink" + + mnt, err := ioutil.TempDir(test_helpers.TmpDir, "reverse_mnt_") + if err != nil { + t.Fatal(err) + } + + sock := mnt + ".sock" + test_helpers.MountOrFatal(t, "ctlsock_reverse_test_fs", mnt, "-reverse", "-extpass", "echo test", "-ctlsock="+sock) + defer test_helpers.UnmountPanic(mnt) + + req := ctlsock.RequestStruct{EncryptPath: symlink} + symlinkResponse := test_helpers.QueryCtlSock(t, sock, req) + if symlinkResponse.ErrNo != 0 { + t.Errorf("Encrypt: %q ErrNo=%d ErrText=%s", symlink, symlinkResponse.ErrNo, symlinkResponse.ErrText) + } + + fi, err := os.Lstat(mnt + "/" + symlinkResponse.Result) + if err != nil { + t.Errorf("Lstat: %v", err) + } + + target, err := os.Readlink(mnt + "/" + symlinkResponse.Result) + if err != nil { + t.Errorf("Readlink: %v", err) + } + + if fi.Size() != int64(len(target)) { + t.Errorf("Lstat reports that symbolic link %q's dentry size is %d, but this does not "+ + "match the length of the string returned by readlink, which is %d.", + symlink, fi.Size(), len(target)) + } +} + // .gocryptfs.reverse.conf in the plaintext dir should be visible as // gocryptfs.conf func TestConfigMapping(t *testing.T) { diff --git a/tests/reverse/ctlsock_reverse_test_fs/a_symlink b/tests/reverse/ctlsock_reverse_test_fs/a_symlink new file mode 120000 index 0000000..06ed148 --- /dev/null +++ b/tests/reverse/ctlsock_reverse_test_fs/a_symlink @@ -0,0 +1 @@ +dir/dir/file \ No newline at end of file