aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/osutil/osutil_linux.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2026-01-09 14:39:39 +0100
committerDmitry Vyukov <dvyukov@google.com>2026-01-09 16:55:27 +0000
commitbc54aa9fe40d6d1ffa6f80a1e04a18689ddbc54c (patch)
tree471210fbf516a516aaa4e15e3bbb99d037fb2177 /pkg/osutil/osutil_linux.go
parent36eb9783384b89dffb86e2eed340838f1b3ff1c1 (diff)
pkg/osutil: fix CreationTime
We return Ctime from CreationTime. But "C" does not stand for "creation", it stands for "status change" (inode update). It may or may not be the creation time. Use Btime (birth time) for creation time. Fixes #6547
Diffstat (limited to 'pkg/osutil/osutil_linux.go')
-rw-r--r--pkg/osutil/osutil_linux.go17
1 files changed, 14 insertions, 3 deletions
diff --git a/pkg/osutil/osutil_linux.go b/pkg/osutil/osutil_linux.go
index 50be9b047..5ab639280 100644
--- a/pkg/osutil/osutil_linux.go
+++ b/pkg/osutil/osutil_linux.go
@@ -18,9 +18,20 @@ import (
"golang.org/x/sys/unix"
)
-func creationTime(fi os.FileInfo) time.Time {
- st := fi.Sys().(*syscall.Stat_t)
- return time.Unix(int64(st.Ctim.Sec), int64(st.Ctim.Nsec)) // nolint: unconvert
+func fileTimes(file string) (time.Time, time.Time, error) {
+ // Btime stands for "birth" time, which is creation time.
+ var statx unix.Statx_t
+ err := unix.Statx(unix.AT_FDCWD, file, unix.AT_SYMLINK_NOFOLLOW, unix.STATX_BTIME|unix.STATX_MTIME, &statx)
+ if err != nil {
+ return time.Time{}, time.Time{}, err
+ }
+ modTime := time.Unix(statx.Mtime.Sec, int64(statx.Mtime.Nsec))
+ // Some filesystems may not store the birth time.
+ creationTime := modTime
+ if statx.Mask&unix.STATX_BTIME != 0 {
+ creationTime = time.Unix(statx.Btime.Sec, int64(statx.Btime.Nsec))
+ }
+ return creationTime, modTime, nil
}
// RemoveAll is similar to os.RemoveAll, but can handle more cases.