forked from security/hakurei
internal/pkg: override "." for directory checksum
This makes the checksum consistent with the final resting state of artifact directories without incurring the cost of an extra pair of chown syscalls. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -376,6 +376,63 @@ func removeAll(pathname *check.Absolute) (chmodErr, removeErr error) {
|
||||
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 }
|
||||
|
||||
// Mode returns [fs.FileMode] with its permission bits set to 0500.
|
||||
func (fi overrideFileInfo) Mode() fs.FileMode {
|
||||
return fi.FileInfo.Mode()&(^fs.FileMode(0777)) | 0500
|
||||
}
|
||||
|
||||
// Sys returns nil to avoid passing the original permission bits.
|
||||
func (fi overrideFileInfo) Sys() any { return nil }
|
||||
|
||||
// overrideFile overrides the permission bits of [fs.File] to 0500 and is the
|
||||
// concrete type returned by dotOverrideFS for calls with "." passed as name.
|
||||
type overrideFile struct{ fs.File }
|
||||
|
||||
func (f overrideFile) Stat() (fi fs.FileInfo, err error) {
|
||||
fi, err = f.File.Stat()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fi = overrideFileInfo{fi}
|
||||
return
|
||||
}
|
||||
|
||||
// dirFS is implemented by the concrete type of the return value of [os.DirFS].
|
||||
type dirFS interface {
|
||||
fs.StatFS
|
||||
fs.ReadFileFS
|
||||
fs.ReadDirFS
|
||||
fs.ReadLinkFS
|
||||
}
|
||||
|
||||
// dotOverrideFS overrides the permission bits of "." to 0500 to avoid the extra
|
||||
// system calls to add and remove write bit from the target directory.
|
||||
type dotOverrideFS struct{ dirFS }
|
||||
|
||||
// Open wraps the underlying [fs.FS] with "." special case.
|
||||
func (fsys dotOverrideFS) Open(name string) (f fs.File, err error) {
|
||||
f, err = fsys.dirFS.Open(name)
|
||||
if err != nil || name != "." {
|
||||
return
|
||||
}
|
||||
f = overrideFile{f}
|
||||
return
|
||||
}
|
||||
|
||||
// Stat wraps the underlying [fs.FS] with "." special case.
|
||||
func (fsys dotOverrideFS) Stat(name string) (fi fs.FileInfo, err error) {
|
||||
fi, err = fsys.dirFS.Stat(name)
|
||||
if err != nil || name != "." {
|
||||
return
|
||||
}
|
||||
fi = overrideFileInfo{fi}
|
||||
return
|
||||
}
|
||||
|
||||
// Cure cures the [Artifact] and returns its pathname and [Checksum].
|
||||
func (c *Cache) Cure(a Artifact) (
|
||||
pathname *check.Absolute,
|
||||
@@ -556,13 +613,11 @@ func (c *Cache) Cure(a Artifact) (
|
||||
return
|
||||
}
|
||||
|
||||
// override this before hashing since it will be made read-only after
|
||||
// the rename anyway so do not let perm bits affect the checksum
|
||||
if err = os.Chmod(workPathname.String(), 0700); err != nil {
|
||||
return
|
||||
}
|
||||
var gotChecksum Checksum
|
||||
if gotChecksum, err = HashDir(workPathname); err != nil {
|
||||
if gotChecksum, err = HashFS(
|
||||
dotOverrideFS{os.DirFS(workPathname.String()).(dirFS)},
|
||||
".",
|
||||
); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -583,6 +638,9 @@ func (c *Cache) Cure(a Artifact) (
|
||||
}
|
||||
}
|
||||
|
||||
if err = os.Chmod(workPathname.String(), 0700); err != nil {
|
||||
return
|
||||
}
|
||||
c.checksumMu.Lock()
|
||||
if err = os.Rename(
|
||||
workPathname.String(),
|
||||
|
||||
Reference in New Issue
Block a user