Skip to content

Commit

Permalink
Preserve APK timestamps when using dirfs (#1352)
Browse files Browse the repository at this point in the history
This worked in our happy tarfs path but not in the dirfs path that
melange uses because some runners mount directories rather than actually
packaging the layer up into an image. This made it impossible to test
the timestamps properly in package tests because the APK files had
modtimes set to SOURCE_DATE_EPOCH.

Signed-off-by: Jon Johnson <[email protected]>
  • Loading branch information
jonjohnsonjr authored Oct 22, 2024
1 parent a5dd405 commit 4e38dc8
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 4 deletions.
4 changes: 4 additions & 0 deletions pkg/apk/apk/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,10 @@ func (a *APK) installAPKFiles(ctx context.Context, in io.Reader, pkg *Package) (

if installed {
a.installedFiles[header.Name] = pkg

if err := a.fs.Chtimes(header.Name, header.AccessTime, header.ModTime); err != nil {
return nil, fmt.Errorf("chtimes for %s: %w", header.Name, err)
}
}

case tar.TypeSymlink:
Expand Down
2 changes: 2 additions & 0 deletions pkg/apk/fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package fs
import (
"io"
"io/fs"
"time"
)

// FullFS is a filesystem that supports all filesystem operations.
Expand All @@ -39,6 +40,7 @@ type FullFS interface {
Remove(name string) error
Chmod(path string, perm fs.FileMode) error
Chown(path string, uid int, gid int) error
Chtimes(path string, atime time.Time, mtime time.Time) error
SetXattr(path string, attr string, data []byte) error
GetXattr(path string, attr string) ([]byte, error)
RemoveXattr(path string, attr string) error
Expand Down
10 changes: 10 additions & 0 deletions pkg/apk/fs/memfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ func (m *memFS) Chmod(path string, perm fs.FileMode) error {
anode.mode = perm | (anode.mode & os.ModeType)
return nil
}

func (m *memFS) Chown(path string, uid, gid int) error {
anode, err := m.getNode(path)
if err != nil {
Expand All @@ -374,6 +375,15 @@ func (m *memFS) Chown(path string, uid, gid int) error {
return nil
}

func (m *memFS) Chtimes(path string, atime time.Time, mtime time.Time) error {
anode, err := m.getNode(path)
if err != nil {
return err
}
anode.modTime = mtime
return nil
}

func (m *memFS) Create(name string) (File, error) {
return m.OpenFile(name, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0o666)
}
Expand Down
8 changes: 8 additions & 0 deletions pkg/apk/fs/rwosfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,7 @@ func (f *dirFS) Chmod(path string, perm fs.FileMode) error {
}
return f.overrides.Chmod(path, perm)
}

func (f *dirFS) Chown(path string, uid, gid int) error {
if f.caseSensitiveOnDisk(path) {
// ignore error, as we track it in memory anyways, and disk filesystem might not support it
Expand All @@ -512,6 +513,13 @@ func (f *dirFS) Chown(path string, uid, gid int) error {
return f.overrides.Chown(path, uid, gid)
}

func (f *dirFS) Chtimes(path string, atime time.Time, mtime time.Time) error {
if err := os.Chtimes(filepath.Join(f.base, path), atime, mtime); err != nil {
return fmt.Errorf("unable to change times: %w", err)
}
return f.overrides.Chtimes(path, atime, mtime)
}

func (f *dirFS) Mknod(name string, mode uint32, dev int) error {
if f.caseSensitiveOnDisk(name) {
err := unix.Mknod(filepath.Join(f.base, name), mode, dev)
Expand Down
5 changes: 1 addition & 4 deletions pkg/build/build_implementation.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,7 @@ func (bc *Context) BuildTarball(ctx context.Context) (string, hash.Hash, hash.Ha
bc.o.TarballPath = outfile.Name()
defer outfile.Close()

// we use a general override of 0,0 for all files, but the specific overrides, that come from the installed package DB, come later
tw, err := tarball.NewContext(
tarball.WithSourceDateEpoch(bc.o.SourceDateEpoch),
)
tw, err := tarball.NewContext()
if err != nil {
return "", nil, nil, 0, fmt.Errorf("failed to construct tarball build context: %w", err)
}
Expand Down
10 changes: 10 additions & 0 deletions pkg/tarfs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,7 @@ func (m *memFS) Chmod(path string, perm fs.FileMode) error {
anode.mode = perm | (anode.mode & os.ModeType)
return nil
}

func (m *memFS) Chown(path string, uid, gid int) error {
anode, err := m.getNode(path)
if err != nil {
Expand All @@ -641,6 +642,15 @@ func (m *memFS) Chown(path string, uid, gid int) error {
return nil
}

func (m *memFS) Chtimes(path string, atime time.Time, mtime time.Time) error {
anode, err := m.getNode(path)
if err != nil {
return err
}
anode.modTime = mtime
return nil
}

func (m *memFS) Create(name string) (apkfs.File, error) {
return m.OpenFile(name, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0o666)
}
Expand Down

0 comments on commit 4e38dc8

Please sign in to comment.