diff --git a/cmd/mbf/daemon_test.go b/cmd/mbf/daemon_test.go index f69ccc59..97b3ba9b 100644 --- a/cmd/mbf/daemon_test.go +++ b/cmd/mbf/daemon_test.go @@ -63,7 +63,7 @@ func TestNoReply(t *testing.T) { } <-done - wantIdent := pkg.MustDecode("fRn1L_pE6JbizdDOKS9GiZXEIp_yx4YYz_nSuv423hGnxAI2rUAwnR1OG1zjsP0N") + wantIdent := pkg.MustDecode("bpVsJ69hdKPBntMh_u777g7-quFNVmMlBJQOlM_thiQa9JnOFLAbe5OlR4zNjZ32") if gotIdent := c.Ident(a).Value(); gotIdent != wantIdent { t.Errorf( "cureFromIR: %s, want %s", @@ -124,7 +124,7 @@ func TestDaemon(t *testing.T) { cancel() <-done - const want = "fRn1L_pE6JbizdDOKS9GiZXEIp_yx4YYz_nSuv423hGnxAI2rUAwnR1OG1zjsP0N" + const want = "bpVsJ69hdKPBntMh_u777g7-quFNVmMlBJQOlM_thiQa9JnOFLAbe5OlR4zNjZ32" if got := filepath.Base(p.String()); got != want { t.Errorf("cureRemote: %s, want %s", got, want) } @@ -132,7 +132,7 @@ func TestDaemon(t *testing.T) { wantLog := []string{ "", "daemon: aborting all pending cures", - "daemon: attempting to cancel invalid artifact C0YO8fkKg38JGK95j8k1tHywA7nMk9xp2TUa69di7uFvnKioTdOOLaDRiwRcs1Nf", + "daemon: attempting to cancel invalid artifact 58Vy_5beLZCvZX__KzRKyIE6vATleaZP1ZBxbqoWnekz9aZ1zkxNgcIUFI5V1_Jf", "daemon: fulfilled artifact " + want, } gotLog := strings.Split(buf.String(), "\n") diff --git a/internal/pkg/archive_test.go b/internal/pkg/archive_test.go index 726c1b6d..1cb4bea9 100644 --- a/internal/pkg/archive_test.go +++ b/internal/pkg/archive_test.go @@ -202,7 +202,7 @@ func TestArchiveArtifact(t *testing.T) { "checksum/CBPcoVHuVUTVRCMbRl8J30RSSzm_tyfuXaZ-HlZsanY1sY50meOVmgaWDrGKbx9F/devices/uevent": {Mode: 0600, Data: []byte("add")}, "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/5woPJTvOnyFA0LpN6fMlw5Z6d3-cfpfNnmEwy5uV8cJi66xQKcfoGNCdVPApuVPW": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CBPcoVHuVUTVRCMbRl8J30RSSzm_tyfuXaZ-HlZsanY1sY50meOVmgaWDrGKbx9F")}, + "identifier/-zXKfphyWM2Ko7VMVURaEMSuixNokFSe0xFbnwR2RtRtvMrcPGWalV0LIn45PXTY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CBPcoVHuVUTVRCMbRl8J30RSSzm_tyfuXaZ-HlZsanY1sY50meOVmgaWDrGKbx9F")}, "substitute": {Mode: fs.ModeDir | 0700}, "work": {Mode: fs.ModeDir | 0700}, diff --git a/internal/pkg/clean_test.go b/internal/pkg/clean_test.go index c67916c3..67dceb09 100644 --- a/internal/pkg/clean_test.go +++ b/internal/pkg/clean_test.go @@ -48,7 +48,7 @@ func TestClean(t *testing.T) { "checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400}, "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/H3WYfuZx1w6bGLUmsSJ35TueazNi8YIsUGTPt4c0ln1rMmZgoDX-LCQt-l0-6UXX": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")}, + "identifier/h6qx7m0vsyhO6oLEJgY2rKa1c6RZuIZ4QXxZSh__NZJ9VU0MIj5bFB-KuaPcsfpE": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")}, "lock": {Mode: 0644}, "variant": {Mode: 0400}, @@ -69,7 +69,7 @@ func TestClean(t *testing.T) { "checksum/KgZ-FjbGuU-XP2QEHInpgv-2Zn0cTH5NqFMgTU0XrSdKmSwyC-3baVs1BMCP5spk": {Mode: 0400, Data: []byte("\xfd")}, "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/vvEdeSwVJ-N39XjgWwXYcd_M1BgoGKLnNqFL6VF3CM1lNAhDHyKu5WcDdf1U-8iO": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/KgZ-FjbGuU-XP2QEHInpgv-2Zn0cTH5NqFMgTU0XrSdKmSwyC-3baVs1BMCP5spk")}, + "identifier/tkrOYhQfTRaArk4nNYNjTmHQUmuJMVIoDeAKIQBm3I4uuMimBKXKMIY2gGZqwQg4": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/KgZ-FjbGuU-XP2QEHInpgv-2Zn0cTH5NqFMgTU0XrSdKmSwyC-3baVs1BMCP5spk")}, "lock": {Mode: 0644}, "variant": {Mode: 0400}, @@ -122,8 +122,8 @@ func TestClean(t *testing.T) { "checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE/result": {Mode: 0444}, "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/nYVS5wRWFw6kro44ZpRRfxduteOY36xu0jHuT4qE3l9rPiFCNxy4RMOnwTLErDx7": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/H-eSiCo227-xdqyNl2R-5G3eqXPtbb8XegAB70I5OQb2majeZXJoCxTq9wJy5qqv")}, - "identifier/-p_RKDFOHplXBB2S6wuf2CkA82u6G3jb_IfEi29KB_vi0wnzcGvRjpTx0989-JxJ": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")}, + "identifier/KpxTUsUfGbsX6C6HU2j9cd9He3_tt2o2m2MgH4m0zial8lmoqSWY-Gc3KrS0k-UK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/H-eSiCo227-xdqyNl2R-5G3eqXPtbb8XegAB70I5OQb2majeZXJoCxTq9wJy5qqv")}, + "identifier/xxQ43VMIS1WHMSEFnUdBNd6pulbtgiTorP_mtJpEsZENYhGBiDEL6Y2D8yqn0Sra": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")}, "lock": {Mode: 0644}, "variant": {Mode: 0400}, @@ -199,14 +199,14 @@ func TestClean(t *testing.T) { "checksum/H-eSiCo227-xdqyNl2R-5G3eqXPtbb8XegAB70I5OQb2majeZXJoCxTq9wJy5qqv": {Mode: 0400, Data: []byte("kept")}, "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/nYVS5wRWFw6kro44ZpRRfxduteOY36xu0jHuT4qE3l9rPiFCNxy4RMOnwTLErDx7": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/H-eSiCo227-xdqyNl2R-5G3eqXPtbb8XegAB70I5OQb2majeZXJoCxTq9wJy5qqv")}, - "identifier/-p_RKDFOHplXBB2S6wuf2CkA82u6G3jb_IfEi29KB_vi0wnzcGvRjpTx0989-JxJ": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CyDnDvF-LaeGPcSW70tPosNCoclByWkTjznUUF1DcgzlIwkN9yzz1ZFME1TlPj6W")}, + "identifier/KpxTUsUfGbsX6C6HU2j9cd9He3_tt2o2m2MgH4m0zial8lmoqSWY-Gc3KrS0k-UK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/H-eSiCo227-xdqyNl2R-5G3eqXPtbb8XegAB70I5OQb2majeZXJoCxTq9wJy5qqv")}, + "identifier/xxQ43VMIS1WHMSEFnUdBNd6pulbtgiTorP_mtJpEsZENYhGBiDEL6Y2D8yqn0Sra": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CyDnDvF-LaeGPcSW70tPosNCoclByWkTjznUUF1DcgzlIwkN9yzz1ZFME1TlPj6W")}, "lock": {Mode: 0644}, "variant": {Mode: 0400}, "status": {Mode: fs.ModeDir | 0700}, - "status/-p_RKDFOHplXBB2S6wuf2CkA82u6G3jb_IfEi29KB_vi0wnzcGvRjpTx0989-JxJ": {Mode: 0400, Data: []byte(statusHeader + "kept")}, + "status/xxQ43VMIS1WHMSEFnUdBNd6pulbtgiTorP_mtJpEsZENYhGBiDEL6Y2D8yqn0Sra": {Mode: 0400, Data: []byte(statusHeader + "kept")}, "status/td1tf1kb3z8iUFg2k1xlHeTTEz3xR4e77WSWdv2JhjmZyY6iuvodhdT8BblDOi0E": {Mode: 0400, Data: []byte(statusHeader + "kept")}, "substitute": {Mode: fs.ModeDir | 0700}, diff --git a/internal/pkg/compress.go b/internal/pkg/compress.go index 50303419..9a0c1152 100644 --- a/internal/pkg/compress.go +++ b/internal/pkg/compress.go @@ -91,6 +91,9 @@ func (c compoundCloser) Close() error { return err } +// IsExecutable returns false. +func (*decompressArtifact) IsExecutable() bool { return false } + // Cure returns a decompressor [io.ReadCloser]. func (a *decompressArtifact) Cure(r *RContext) (io.ReadCloser, error) { sr, err := r.Open(a.f) diff --git a/internal/pkg/file.go b/internal/pkg/file.go index 1b6b02f7..14467153 100644 --- a/internal/pkg/file.go +++ b/internal/pkg/file.go @@ -12,6 +12,7 @@ type fileArtifact []byte var _ KnownChecksum = new(fileArtifact) var _ CuresExempt = new(fileArtifact) +var _ RevisionArtifact = new(fileArtifact) // fileArtifactNamed embeds fileArtifact alongside a caller-supplied name. type fileArtifactNamed struct { @@ -76,6 +77,20 @@ func (a *fileArtifact) Checksum() Checksum { return Checksum(h.Sum(nil)) } +// Revision satisfies [RevisionArtifact] for incompatible IsExecutable behaviour. +func (*fileArtifact) Revision() uint64 { return 0 } + +// IsExecutable returns whether the contents begin with shebang or the ELF +// magic number. +func (a *fileArtifact) IsExecutable() bool { + return a != nil && + (bytes.HasPrefix( + *a, []byte{'#', '!'}, + ) || bytes.HasPrefix( + *a, []byte{0x7f, 'E', 'L', 'F'}, + )) +} + // Cure returns the caller-supplied data. func (a *fileArtifact) Cure(*RContext) (io.ReadCloser, error) { return io.NopCloser(bytes.NewReader(*a)), nil diff --git a/internal/pkg/file_test.go b/internal/pkg/file_test.go index 0111faa8..f6fcc96f 100644 --- a/internal/pkg/file_test.go +++ b/internal/pkg/file_test.go @@ -12,22 +12,41 @@ func TestFile(t *testing.T) { t.Parallel() want := expectsFile{0} + const ident = "N7M6W8-e55Wky_1q1a6qRKFVDw1S5XtPdB4HE2YZObG8OFum8HittyJgZUG5Ru2u" + wantShebang := expectsFile("#!/bin/sh\n") + const identShebang = "oKTGZb_TRtJf5G1iGGj4SOx1WUbI6YhmsUeEsCNvmK9tZYRwdwQf-DLFUxRPx5qm" + wantELF := expectsFile("\x7fELF\xde\xad\xbe\xef") + const identELF = "LjeHmIJgD1SiXIH8ewpGRed2_LU84NLapstnOAa_0hxLd8YY7x4KM0aApsj-RwCh" checkWithCache(t, []cacheTestCase{ {"file", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) { cureMany(t, c, []cureStep{ - {"short", pkg.NewFile("null", []byte{0}), base.Append( + {"short", pkg.NewFile("null", want), base.Append( "identifier", - "J3quqJoHNQID_k-amRdanjl0nXynlU7wzVJUx25BNvL229wxPyQ9s2Td9VbnRP6s", + ident, ), want, pkg.WNew, nil}, + + {"shebang", pkg.NewFile("shebang", wantShebang), base.Append( + "identifier", + identShebang, + ), wantShebang, pkg.WNew, nil}, + + {"elf", pkg.NewFile("ELF", wantELF), base.Append( + "identifier", + identELF, + ), wantELF, pkg.WNew, nil}, }) }, expectsFS{ ".": {Mode: fs.ModeDir | 0700}, - "checksum": {Mode: fs.ModeDir | 0700}, - "checksum/" + pkg.Encode(want.hash()): {Mode: 0400, Data: []byte{0}}, + "checksum": {Mode: fs.ModeDir | 0700}, + "checksum/" + pkg.Encode(want.hash()): {Mode: 0400, Data: want}, + "checksum/" + pkg.Encode(wantShebang.hash()): {Mode: 0500, Data: wantShebang}, + "checksum/" + pkg.Encode(wantELF.hash()): {Mode: 0500, Data: wantELF}, - "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/J3quqJoHNQID_k-amRdanjl0nXynlU7wzVJUx25BNvL229wxPyQ9s2Td9VbnRP6s": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")}, + "identifier": {Mode: fs.ModeDir | 0700}, + "identifier/" + ident: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + pkg.Encode(want.hash()))}, + "identifier/" + identShebang: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + pkg.Encode(wantShebang.hash()))}, + "identifier/" + identELF: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + pkg.Encode(wantELF.hash()))}, "substitute": {Mode: fs.ModeDir | 0700}, diff --git a/internal/pkg/ir_test.go b/internal/pkg/ir_test.go index 963cdc04..312474bc 100644 --- a/internal/pkg/ir_test.go +++ b/internal/pkg/ir_test.go @@ -4,7 +4,6 @@ import ( "bytes" "io" "io/fs" - "math" "reflect" "testing" @@ -154,7 +153,7 @@ func TestRevision(t *testing.T) { p := buf.Bytes() p[8] = 0xfd - wantErr := pkg.RevisionError{math.MaxUint64 - 2, math.MaxUint64} + wantErr := pkg.RevisionError{0xfd, 0} if _, err := c.NewDecoder( bytes.NewReader(p), ).Decode(); !reflect.DeepEqual(err, wantErr) { diff --git a/internal/pkg/net.go b/internal/pkg/net.go index 412dd2a7..cd30e3bb 100644 --- a/internal/pkg/net.go +++ b/internal/pkg/net.go @@ -74,6 +74,9 @@ func (e ResponseStatusError) Error() string { return "the requested URL returned non-OK status: " + http.StatusText(int(e)) } +// IsExecutable returns false. +func (*httpArtifact) IsExecutable() bool { return false } + // Cure sends the http request and returns the resulting response body reader // wrapped to perform checksum validation. It is valid but not encouraged to // close the resulting [io.ReadCloser] before it is read to EOF, as that causes diff --git a/internal/pkg/pkg.go b/internal/pkg/pkg.go index ae3a8185..f837fade 100644 --- a/internal/pkg/pkg.go +++ b/internal/pkg/pkg.go @@ -478,6 +478,8 @@ type KnownIdent interface { // [Artifact]. This value must be known ahead of time and guaranteed to be // unique without having obtained the full contents of the [Artifact]. ID() ID + + Artifact } // KnownChecksum is optionally implemented by [Artifact] for an artifact with @@ -489,6 +491,8 @@ type KnownChecksum interface { // // Result must remain identical across multiple invocations. Checksum() Checksum + + Artifact } // CuresExempt is optionally implemented for an artifact exempt to the @@ -506,6 +510,12 @@ type CuresExempt interface { // FileArtifact does not support fine-grained cancellation. Its context is // inherited from the first [TrivialArtifact] or [FloodArtifact] that opens it. type FileArtifact interface { + // IsExecutable returns whether the resulting filesystem entry should be made + // executable, if the [FileArtifact] is cured to the on-disk cache. + // + // Result must remain identical across multiple invocations. + IsExecutable() bool + // Cure returns [io.ReadCloser] of the full contents of [FileArtifact]. If // [FileArtifact] implements [KnownChecksum], Cure is responsible for // validating any data it produces and must return [ChecksumMismatchError] @@ -515,7 +525,8 @@ type FileArtifact interface { // // Callers are responsible for closing the resulting [io.ReadCloser]. // - // Result must remain identical across multiple invocations. + // The resulting [io.ReadCloser] across multiple invocations must have + // identical behaviour. Cure(r *RContext) (io.ReadCloser, error) Artifact @@ -2208,12 +2219,17 @@ func (c *Cache) cure(a Artifact, curesExempt, rebuild bool) ( return } + perm := os.FileMode(0400) + if f.IsExecutable() { + perm = 0500 + } + work := c.base.Append(dirWork, ids) var w *os.File if w, err = os.OpenFile( work.String(), os.O_CREATE|os.O_EXCL|os.O_WRONLY, - 0400, + perm, ); err != nil { return } diff --git a/internal/pkg/pkg_test.go b/internal/pkg/pkg_test.go index b9098c0c..1313d42c 100644 --- a/internal/pkg/pkg_test.go +++ b/internal/pkg/pkg_test.go @@ -170,6 +170,8 @@ type stubFile struct { stubArtifact } +func (*stubFile) IsExecutable() bool { return false } + func (a *stubFile) Cure(*pkg.RContext) (io.ReadCloser, error) { return io.NopCloser(bytes.NewReader(a.data)), a.err } @@ -1510,14 +1512,14 @@ func TestCache(t *testing.T) { "checksum/wILUy2izpj2sgKJVhGUGIAde1XVuqvp5BpFMIQHanT5Q8R6jK4QPVSrJsjZh-njV": {Mode: 0400, Data: []byte("destroyed")}, "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/2vZYAE7AVme2W3EgcDP1QUfwrmgFWIswUQBd6ZIBtiCal-MLiCtAg940Jzed5w4_": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")}, - "identifier/42lkARs2-xl_7wXfjPB0DaOXH8U2BKimaDYX-POJv5l01ArTKMbABt_kUMp24F1U": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/wILUy2izpj2sgKJVhGUGIAde1XVuqvp5BpFMIQHanT5Q8R6jK4QPVSrJsjZh-njV")}, - "identifier/H5pfX9loHFLORmMrMFCDbVUGg0RtxUDj4GHs21Q6bD8PTiAaFVGLnTQlhbMC5Z0G": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")}, - "identifier/sZVN1nOxhdWvZnus3nPTe6q0SqqzObfNBsJNnVu6Co6ajKA9wCiUP33MOdaaEt7K": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/wILUy2izpj2sgKJVhGUGIAde1XVuqvp5BpFMIQHanT5Q8R6jK4QPVSrJsjZh-njV")}, + "identifier/CLyyxJWn1yUGFs_0KnJ4ZSU2hH4-elvGFRB36x14LrNrKBJPxvORhL9O4Rc7oeYU": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/wILUy2izpj2sgKJVhGUGIAde1XVuqvp5BpFMIQHanT5Q8R6jK4QPVSrJsjZh-njV")}, + "identifier/arv8a6z4i0x6pUb5Z2T-3iE4ETvyZj-uReHGKsS7uiBgMgKNEOzTGG3LIZb8vp0L": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/wILUy2izpj2sgKJVhGUGIAde1XVuqvp5BpFMIQHanT5Q8R6jK4QPVSrJsjZh-njV")}, + "identifier/heRgWhNJmhm898V68kw0ta76t4rP1o29tYW_TrdyBWXGfo37K3QWA7Z-JkLXAwcn": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")}, + "identifier/q-VoVBI3IjcWTqwIokpi3y05CP113CHgHslc-XWnhOvDULwzVc3q9Y5xOCm_YyLZ": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")}, "status": {Mode: fs.ModeDir | 0700}, - "status/H5pfX9loHFLORmMrMFCDbVUGg0RtxUDj4GHs21Q6bD8PTiAaFVGLnTQlhbMC5Z0G": {Mode: fs.ModeSymlink | 0777, Data: []byte("dP-6_wIDRRouOaOF-nkBy-IaUbLdYHbOUTrptu7j_qfW01mnHSjYJ0oykUmvUd2x")}, - "status/2vZYAE7AVme2W3EgcDP1QUfwrmgFWIswUQBd6ZIBtiCal-MLiCtAg940Jzed5w4_": {Mode: 0400, Data: []byte(statusHeader + "destroyed")}, + "status/q-VoVBI3IjcWTqwIokpi3y05CP113CHgHslc-XWnhOvDULwzVc3q9Y5xOCm_YyLZ": {Mode: fs.ModeSymlink | 0777, Data: []byte("dP-6_wIDRRouOaOF-nkBy-IaUbLdYHbOUTrptu7j_qfW01mnHSjYJ0oykUmvUd2x")}, + "status/heRgWhNJmhm898V68kw0ta76t4rP1o29tYW_TrdyBWXGfo37K3QWA7Z-JkLXAwcn": {Mode: 0400, Data: []byte(statusHeader + "destroyed")}, "status/dP-6_wIDRRouOaOF-nkBy-IaUbLdYHbOUTrptu7j_qfW01mnHSjYJ0oykUmvUd2x": {Mode: 0400, Data: []byte(statusHeader + "destroyed")}, "substitute": {Mode: fs.ModeDir | 0700}, @@ -1613,10 +1615,10 @@ func TestCache(t *testing.T) { "checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl/result": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent")}, "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/PITQy8S3pqQRTJOE9lPJVjUMri6jSuknElXX7SaUVtUTQqByg79dI-kpc6J2GNeY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, - "identifier/TI4SrHTEYRZ9yeiJzPqPULx4pl1hVSFgZ7DTweQSwk49k8lAIC1A5UrPs45P3Hi6": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, - "identifier/xCv2q_KJpNoTkXI9ua5UMAC1ndSrCeAhlQ9njUcwXCSd_qAnSXkgOy7uluHWWD3o": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, - "identifier/DyLrgassC_E06vPgPzQFuCOxwoccc08C04FSuI6aliWWXdJLWnJt9R9OXwoakhhm": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")}, + "identifier/k8yyhlBV3JpYzzywAnrRWkfp2TmgIDNC6FqMFwrrR2x0C3unBLveDNKgigOjG9MM": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, + "identifier/Xys8hPpJsKirZmTTuT7SwQ6661TCp_ZRu8iUjPPD7pC5E3ll7xw4zhNlZ2PVcz_-": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, + "identifier/8sInO_dhPW9kweit7jVuH_vtMkRxlZT7XE4_yEKPZmpGkgVxkmxz0OpXgbMsH6ET": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, + "identifier/ofaXbB5gIza_7W4Rzo5XDe_8FwlCPKWn3TBcmGgFAkkTWMl5GXGmOzX89Jd2Mk2A": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")}, "identifier/8VL-egZySw-RbnHZtxGWdf5Z2v9S9CihrdFwa54Bc5EYMQcEgWEem7QrdCTWlCb8": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, "status": {Mode: fs.ModeDir | 0700}, @@ -1756,12 +1758,12 @@ func TestCache(t *testing.T) { "checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl/result": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent")}, "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/xCv2q_KJpNoTkXI9ua5UMAC1ndSrCeAhlQ9njUcwXCSd_qAnSXkgOy7uluHWWD3o": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, - "identifier/uaLFpraDJ8JOCFT94FhrVCNn9R2iXozSw3W4Rt_zdAKhlViF36CGjjwL6IJoe4fU": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, - "identifier/aCVm-QVKHmWPyHu02CjnJ5xXlIr78nNQRv1x9HhFRamQkaYesdubZFy-m7JxI38v": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, - "identifier/PITQy8S3pqQRTJOE9lPJVjUMri6jSuknElXX7SaUVtUTQqByg79dI-kpc6J2GNeY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, + "identifier/3fYJjSiWhklt7TK9MPVLGk5_8AIU8ostTcFPXULJf_qeAVG6pmC-Cqqu4ZhEXRxn": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, "identifier/8VL-egZySw-RbnHZtxGWdf5Z2v9S9CihrdFwa54Bc5EYMQcEgWEem7QrdCTWlCb8": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, - "identifier/TI4SrHTEYRZ9yeiJzPqPULx4pl1hVSFgZ7DTweQSwk49k8lAIC1A5UrPs45P3Hi6": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, + "identifier/8sInO_dhPW9kweit7jVuH_vtMkRxlZT7XE4_yEKPZmpGkgVxkmxz0OpXgbMsH6ET": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, + "identifier/Xys8hPpJsKirZmTTuT7SwQ6661TCp_ZRu8iUjPPD7pC5E3ll7xw4zhNlZ2PVcz_-": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, + "identifier/k8yyhlBV3JpYzzywAnrRWkfp2TmgIDNC6FqMFwrrR2x0C3unBLveDNKgigOjG9MM": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, + "identifier/mXlNz_v77nW7jstn_rJn4RL7dCQlkakM0y-HjO6tkDubtzaj-wCmW1hIr2Gk64_O": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, "status": {Mode: fs.ModeDir | 0700}, "status/8VL-egZySw-RbnHZtxGWdf5Z2v9S9CihrdFwa54Bc5EYMQcEgWEem7QrdCTWlCb8": {Mode: 0400, Data: []byte("\x00")},