2021-03-21 11:10:18 +01:00
|
|
|
// test gocryptfs cipherdir mounted multiple times at the same time
|
|
|
|
package sharedstorage
|
|
|
|
|
|
|
|
import (
|
2021-03-30 14:58:18 +02:00
|
|
|
"fmt"
|
|
|
|
"os"
|
2021-03-21 11:10:18 +01:00
|
|
|
"testing"
|
2021-03-30 14:58:18 +02:00
|
|
|
"time"
|
2021-03-21 11:10:18 +01:00
|
|
|
|
|
|
|
"golang.org/x/sys/unix"
|
|
|
|
|
2021-08-23 15:05:15 +02:00
|
|
|
"github.com/rfjakob/gocryptfs/v2/tests/test_helpers"
|
2021-03-21 11:10:18 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
var flagSharestorage bool
|
|
|
|
|
2021-04-02 20:22:26 +02:00
|
|
|
// EntryTimeout is 1 second, give the kernel 1.1 second to actually
|
|
|
|
// expire an entry. The tests fail sometime with 1.0 second!
|
|
|
|
const waitForExpire = time.Second + 100*time.Millisecond
|
2021-03-30 14:58:18 +02:00
|
|
|
|
2021-03-21 11:10:18 +01:00
|
|
|
func TestMain(m *testing.M) {
|
2021-03-30 14:58:18 +02:00
|
|
|
ret := 0
|
2021-03-21 11:10:18 +01:00
|
|
|
flagSharestorage = false
|
2021-03-30 14:58:18 +02:00
|
|
|
ret += m.Run()
|
2021-03-21 11:10:18 +01:00
|
|
|
flagSharestorage = true
|
2021-03-30 14:58:18 +02:00
|
|
|
ret += m.Run()
|
|
|
|
os.Exit(ret)
|
|
|
|
}
|
|
|
|
|
|
|
|
type testCase struct {
|
|
|
|
t *testing.T
|
|
|
|
|
|
|
|
cipherdir string
|
|
|
|
mnt1 string
|
|
|
|
mnt2 string
|
|
|
|
}
|
|
|
|
|
|
|
|
func newTestCase(t *testing.T) *testCase {
|
|
|
|
tc := testCase{}
|
|
|
|
tc.cipherdir = test_helpers.InitFS(t)
|
|
|
|
tc.mnt1 = tc.cipherdir + ".mnt1"
|
|
|
|
tc.mnt2 = tc.cipherdir + ".mnt2"
|
|
|
|
mountSharedstorage(t, tc.cipherdir, tc.mnt1)
|
|
|
|
mountSharedstorage(t, tc.cipherdir, tc.mnt2)
|
|
|
|
t.Logf("newTestCase: sharedstorage=%v cipherdir=%q", flagSharestorage, tc.cipherdir)
|
|
|
|
return &tc
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tc *testCase) cleanup() {
|
|
|
|
for _, mnt := range []string{tc.mnt1, tc.mnt2} {
|
|
|
|
err := test_helpers.UnmountErr(mnt)
|
|
|
|
if err != nil {
|
|
|
|
tc.t.Error(err)
|
|
|
|
}
|
|
|
|
}
|
2021-03-21 11:10:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// mountSharedstorage mounts `cipherdir` on `mnt` with or without the
|
|
|
|
// `-sharedstorage` flag, depending on the global var `flagSharestorage`.
|
|
|
|
func mountSharedstorage(t *testing.T, cipherdir string, mnt string) {
|
|
|
|
args := []string{"-extpass=echo test"}
|
|
|
|
if flagSharestorage {
|
|
|
|
args = append(args, "-sharedstorage")
|
|
|
|
}
|
|
|
|
test_helpers.MountOrFatal(t, cipherdir, mnt, args...)
|
|
|
|
}
|
|
|
|
|
2021-03-30 14:58:18 +02:00
|
|
|
func TestDirUnlink(t *testing.T) {
|
|
|
|
tc := newTestCase(t)
|
|
|
|
defer tc.cleanup()
|
2021-03-21 11:10:18 +01:00
|
|
|
|
|
|
|
// Create dir via mnt1
|
2021-03-30 14:58:18 +02:00
|
|
|
if err := unix.Mkdir(tc.mnt1+"/foo", 0700); err != nil {
|
2021-03-21 11:10:18 +01:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
// Replace dir with file via mnt2
|
2021-03-30 14:58:18 +02:00
|
|
|
if err := unix.Rmdir(tc.mnt2 + "/foo"); err != nil {
|
2021-03-21 11:10:18 +01:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2021-12-08 18:49:21 +01:00
|
|
|
if fd, err := unix.Open(tc.mnt2+"/foo", unix.O_CREAT|unix.O_WRONLY|unix.O_TRUNC, 0600); err != nil {
|
2021-03-21 11:10:18 +01:00
|
|
|
t.Fatal(err)
|
|
|
|
} else {
|
|
|
|
unix.Close(fd)
|
|
|
|
}
|
|
|
|
// Try to unlink via mnt1
|
2021-03-30 14:58:18 +02:00
|
|
|
if err := unix.Unlink(tc.mnt1 + "/foo"); err != nil {
|
|
|
|
// Must work with -sharedstorage
|
|
|
|
if flagSharestorage {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else {
|
|
|
|
// Must always work after cache timeout
|
2021-04-02 20:22:26 +02:00
|
|
|
time.Sleep(waitForExpire)
|
2021-03-30 14:58:18 +02:00
|
|
|
if err := unix.Unlink(tc.mnt1 + "/foo"); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestStaleHardlinks always failed before
|
|
|
|
// https://review.gerrithub.io/c/hanwen/go-fuse/+/513646/2
|
|
|
|
func TestStaleHardlinks(t *testing.T) {
|
|
|
|
tc := newTestCase(t)
|
|
|
|
defer tc.cleanup()
|
|
|
|
|
|
|
|
link0 := tc.mnt1 + "/link0"
|
2021-12-08 18:49:21 +01:00
|
|
|
if fd, err := unix.Open(link0, unix.O_CREAT|unix.O_WRONLY|unix.O_TRUNC, 0600); err != nil {
|
2021-03-30 14:58:18 +02:00
|
|
|
t.Fatal(err)
|
|
|
|
} else {
|
|
|
|
unix.Close(fd)
|
|
|
|
}
|
|
|
|
// Create hardlinks via mnt1
|
|
|
|
for i := 1; i < 20; i++ {
|
|
|
|
linki := fmt.Sprintf(tc.mnt1+"/link%d", i)
|
|
|
|
if err := unix.Link(link0, linki); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Delete hardlinks via mnt2
|
|
|
|
for i := 1; i < 20; i++ {
|
|
|
|
linki := fmt.Sprintf(tc.mnt2+"/link%d", i)
|
|
|
|
if err := unix.Unlink(linki); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Open link0 via mnt1
|
|
|
|
fd, err := unix.Open(link0, unix.O_RDONLY, 0)
|
|
|
|
if err != nil {
|
|
|
|
// Must work with -sharedstorage
|
2021-03-21 11:10:18 +01:00
|
|
|
if flagSharestorage {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else {
|
2021-03-30 14:58:18 +02:00
|
|
|
// Must always work after cache timeout
|
2021-04-02 20:22:26 +02:00
|
|
|
time.Sleep(waitForExpire)
|
2021-03-30 14:58:18 +02:00
|
|
|
fd, err = unix.Open(link0, unix.O_RDONLY, 0)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2021-03-21 11:10:18 +01:00
|
|
|
}
|
|
|
|
}
|
2021-03-30 14:58:18 +02:00
|
|
|
unix.Close(fd)
|
2021-03-21 11:10:18 +01:00
|
|
|
}
|