diff options
Diffstat (limited to 'tests/reverse/correctness_test.go')
-rw-r--r-- | tests/reverse/correctness_test.go | 97 |
1 files changed, 83 insertions, 14 deletions
diff --git a/tests/reverse/correctness_test.go b/tests/reverse/correctness_test.go index b335456..e4684df 100644 --- a/tests/reverse/correctness_test.go +++ b/tests/reverse/correctness_test.go @@ -295,6 +295,23 @@ func TestSeekData(t *testing.T) { f.Close() } +// newWorkdir creates a new empty dir in dirA and returns the full path to it along +// with the corresponding encrypted path in dirB +func newWorkdir(t *testing.T) (workdirA, workdirB string) { + workdirA = dirA + "/" + t.Name() + if err := os.Mkdir(workdirA, 0700); err != nil { + t.Fatal(err) + } + // Find workdir in dirB (=encrypted view) + var st syscall.Stat_t + if err := syscall.Stat(workdirA, &st); err != nil { + t.Fatal(err) + } + workdirB = dirB + "/" + findIno(dirB, st.Ino) + t.Logf("newWorkdir: workdirA=%q workdirB=%q", workdirA, workdirB) + return +} + // gocryptfs.longname.*.name of hardlinked files should not appear hardlinked (as the // contents are different). // @@ -308,28 +325,22 @@ func TestHardlinkedLongname(t *testing.T) { t.Skip() } - workdir := dirA + "/" + t.Name() - if err := os.Mkdir(workdir, 0700); err != nil { - t.Fatal(err) - } - long1 := workdir + "/" + strings.Repeat("x", 200) + workdirA, workdirB := newWorkdir(t) + + long1 := workdirA + "/" + strings.Repeat("x", 200) if err := ioutil.WriteFile(long1, []byte("hello"), 0600); err != nil { t.Fatal(err) } - long2 := workdir + "/" + strings.Repeat("y", 220) - if err := syscall.Link(long1, long2); err != nil { + var long1_stat syscall.Stat_t + if err := syscall.Stat(long1, &long1_stat); err != nil { t.Fatal(err) } - - // Find workdir in encrypted view - var st syscall.Stat_t - if err := syscall.Stat(workdir, &st); err != nil { + long2 := workdirA + "/" + strings.Repeat("y", 220) + if err := syscall.Link(long1, long2); err != nil { t.Fatal(err) } - cWorkdir := dirB + "/" + findIno(dirB, st.Ino) - t.Logf("workdir=%q cWorkdir=%q", workdir, cWorkdir) - matches, err := filepath.Glob(cWorkdir + "/gocryptfs.longname.*.name") + matches, err := filepath.Glob(workdirB + "/gocryptfs.longname.*.name") if err != nil { t.Fatal(err) } @@ -352,3 +363,61 @@ func TestHardlinkedLongname(t *testing.T) { t.Errorf("Files %q have the same inode number - that's wrong!", matches) } } + +// With inode number reuse and hard links, we could have returned +// wrong data for gocryptfs.diriv and gocryptfs.xyz.longname files, respectively +// (https://github.com/rfjakob/gocryptfs/issues/802). +// +// Now that this is fixed, ensure that rsync and similar tools pick up the new +// correct files by advancing mtime and ctime by 10 seconds, which should be more +// than any filesytems' timestamp granularity (FAT32 has 2 seconds). +func TestMtimePlus10(t *testing.T) { + if plaintextnames { + t.Skip("plaintextnames mode does not have virtual files") + } + + workdirA, workdirB := newWorkdir(t) + + long := workdirA + "/" + strings.Repeat("x", 200) + if err := os.WriteFile(long, nil, 0600); err != nil { + t.Fatal(err) + } + long_stat, err := os.Stat(long) + if err != nil { + t.Fatal(err) + } + + workdirA_stat, err := os.Stat(workdirA) + if err != nil { + t.Fatal(err) + } + + // Find and check gocryptfs.longname.*.name + matches, err := filepath.Glob(workdirB + "/gocryptfs.longname.*.name") + if err != nil { + t.Fatal(err) + } + if len(matches) != 1 { + t.Fatal(matches) + } + name_stat, err := os.Stat(matches[0]) + if err != nil { + t.Fatal(err) + } + if name_stat.ModTime().Unix() != long_stat.ModTime().Unix()+10 { + t.Errorf(".name file should show mtime+10") + } + + // Check gocryptfs.diriv + if deterministic_names { + // No gocryptfs.diriv + return + } + diriv_stat, err := os.Stat(workdirB + "/gocryptfs.diriv") + if err != nil { + t.Fatal(err) + } + if diriv_stat.ModTime().Unix() != workdirA_stat.ModTime().Unix()+10 { + t.Errorf("diriv file should show mtime+10") + } +} |