From 1667df9c43324728a0ebf7aaf01f7d7725d9717e Mon Sep 17 00:00:00 2001 From: Ophestra Date: Tue, 13 Jan 2026 01:28:55 +0900 Subject: [PATCH] internal/pkg: zero atime and mtime This is significantly more practical than keeping track of them in directory flattening format and setting this in every non-artifact implementation. Only tarArtifact can have meaningful deterministic checksums that are not zero and zeroing them still keeps autotools happy. Signed-off-by: Ophestra --- internal/pkg/pkg.go | 46 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/internal/pkg/pkg.go b/internal/pkg/pkg.go index a79f66a..3c9fbdb 100644 --- a/internal/pkg/pkg.go +++ b/internal/pkg/pkg.go @@ -19,6 +19,7 @@ import ( "strings" "sync" "syscall" + "unsafe" "hakurei.app/container/check" "hakurei.app/message" @@ -801,6 +802,33 @@ func removeAll(pathname *check.Absolute) (chmodErr, removeErr error) { return } +// zeroTimes zeroes atime and mtime for the named file. +func zeroTimes(path string) (err error) { + // include/uapi/linux/fcntl.h + const ( + AT_FDCWD = -100 + AT_SYMLINK_NOFOLLOW = 0x100 + ) + _AT_FDCWD := AT_FDCWD + + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + if _, _, errno := syscall.Syscall6( + syscall.SYS_UTIMENSAT, + uintptr(_AT_FDCWD), + uintptr(unsafe.Pointer(_p0)), + uintptr(unsafe.Pointer(new([2]syscall.Timespec))), + AT_SYMLINK_NOFOLLOW, + 0, 0, + ); errno != 0 { + return os.NewSyscallError("utimensat", errno) + } + return +} + // overrideFileInfo overrides the permission bits of [fs.FileInfo] to 0500 and // is the concrete type returned by overrideFile.Stat. type overrideFileInfo struct{ fs.FileInfo } @@ -914,6 +942,9 @@ func (c *Cache) Cure(a Artifact) ( checksumLinknamePrefix+checksums, pathname.String(), ) + if err == nil { + err = zeroTimes(pathname.String()) + } } }() @@ -1009,10 +1040,15 @@ func (c *Cache) Cure(a Artifact) ( } _, err = w.Write(data) closeErr := w.Close() + timeErr := zeroTimes(checksumPathname.String()) + c.checksumMu.Unlock() + + if err == nil { + err = timeErr + } if err == nil { err = closeErr } - c.checksumMu.Unlock() return } @@ -1125,6 +1161,14 @@ func (c *Cache) Cure(a Artifact) ( if err = os.Chmod(t.work.String(), 0700); err != nil { return } + if err = filepath.WalkDir(t.work.String(), func(path string, _ fs.DirEntry, err error) error { + if err != nil { + return err + } + return zeroTimes(path) + }); err != nil { + return + } c.checksumMu.Lock() if err = os.Rename( t.work.String(),