restic/internal/fs/setflags_linux_test.go

71 lines
1.5 KiB
Go

package fs
import (
"io"
"os"
"testing"
"time"
rtest "github.com/restic/restic/internal/test"
"golang.org/x/sys/unix"
)
func TestNoatime(t *testing.T) {
f, err := os.CreateTemp("", "restic-test-noatime")
if err != nil {
t.Fatal(err)
}
defer func() {
_ = f.Close()
err = Remove(f.Name())
if err != nil {
t.Fatal(err)
}
}()
// Only run this test on common filesystems that support O_NOATIME.
// On others, we may not get an error.
if !supportsNoatime(t, f) {
t.Skip("temp directory may not support O_NOATIME, skipping")
}
// From this point on, we own the file, so we should not get EPERM.
_, err = io.WriteString(f, "Hello!")
rtest.OK(t, err)
_, err = f.Seek(0, io.SeekStart)
rtest.OK(t, err)
getAtime := func() time.Time {
info, err := f.Stat()
rtest.OK(t, err)
return ExtendedStat(info).AccessTime
}
atime := getAtime()
err = setFlags(f)
rtest.OK(t, err)
_, err = f.Read(make([]byte, 1))
rtest.OK(t, err)
rtest.Equals(t, atime, getAtime())
}
func supportsNoatime(t *testing.T, f *os.File) bool {
var fsinfo unix.Statfs_t
err := unix.Fstatfs(int(f.Fd()), &fsinfo)
rtest.OK(t, err)
// The funky cast works around a compiler error on 32-bit archs:
// "unix.BTRFS_SUPER_MAGIC (untyped int constant 2435016766) overflows int32".
// https://github.com/golang/go/issues/52061
typ := int64(uint(fsinfo.Type))
return typ == unix.BTRFS_SUPER_MAGIC ||
typ == unix.EXT2_SUPER_MAGIC ||
typ == unix.EXT3_SUPER_MAGIC ||
typ == unix.EXT4_SUPER_MAGIC ||
typ == unix.TMPFS_MAGIC
}