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 = os.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 }