diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2026-01-09 14:39:39 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2026-01-09 16:55:27 +0000 |
| commit | bc54aa9fe40d6d1ffa6f80a1e04a18689ddbc54c (patch) | |
| tree | 471210fbf516a516aaa4e15e3bbb99d037fb2177 /pkg/osutil/osutil_linux.go | |
| parent | 36eb9783384b89dffb86e2eed340838f1b3ff1c1 (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.go | 17 |
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. |
