diff options
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/archive.go | 42 | ||||
| -rw-r--r-- | pkg/archive_test.go | 12 | ||||
| -rw-r--r-- | pkg/clean_test.go | 12 | ||||
| -rw-r--r-- | pkg/exec.go | 7 | ||||
| -rw-r--r-- | pkg/internal/testtool/main.go | 4 | ||||
| -rw-r--r-- | pkg/pkg.go | 14 | ||||
| -rw-r--r-- | pkg/pkg_test.go | 32 | ||||
| -rw-r--r-- | pkg/tar.go | 57 | ||||
| -rw-r--r-- | pkg/tar_test.go | 51 |
9 files changed, 193 insertions, 38 deletions
diff --git a/pkg/archive.go b/pkg/archive.go index ea4017d9..e9f76f5b 100644 --- a/pkg/archive.go +++ b/pkg/archive.go @@ -311,8 +311,16 @@ func (a archiveArtifact) Inputs() []Artifact { // IsExclusive returns false: [Reader] is fully sequential. func (archiveArtifact) IsExclusive() bool { return false } +// Revision satisfies [RevisionArtifact] for status behaviour. +func (archiveArtifact) Revision() uint64 { return 0 } + // Cure cures the [Artifact], producing a directory located at work. func (a archiveArtifact) Cure(t *TContext) (err error) { + var status io.Writer + if status, err = t.GetStatusWriter(); err != nil { + return + } + var r io.ReadCloser if r, err = t.Open(a.f); err != nil { return @@ -347,7 +355,9 @@ func (a archiveArtifact) Cure(t *TContext) (err error) { var header *ArchiveHeader ar := NewReader(r) + msg := t.GetMessage() for header, err = ar.Next(); err == nil; header, err = ar.Next() { + var m string if header.Mode.IsRegular() { var f *os.File if f, err = root.OpenFile( @@ -363,18 +373,33 @@ func (a archiveArtifact) Cure(t *TContext) (err error) { } else if err = f.Close(); err != nil { return } + + m = fmt.Sprintf( + "%s %s (%d bytes)", + header.Mode, + header.Path, + header.Size, + ) } else if header.Mode&fs.ModeSymlink != 0 { var p []byte if p, err = io.ReadAll(ar); err != nil { return } + linkname := unsafe.String(unsafe.SliceData(p), len(p)) if err = root.Symlink( - unsafe.String(unsafe.SliceData(p), len(p)), + linkname, header.Path, ); err != nil { return } + + m = fmt.Sprintf( + "%s %s linkname %s", + header.Mode, + header.Path, + linkname, + ) } else if header.Mode.IsDir() { if header.Path == "." { continue @@ -387,9 +412,24 @@ func (a archiveArtifact) Cure(t *TContext) (err error) { if err = root.Mkdir(header.Path, 0700); err != nil { return } + + m = fmt.Sprintf( + "%s %s", + header.Mode, + header.Path, + ) } else { return InvalidFileModeError(header.Mode) } + + if m != "" { + msg.Verbose(m) + if _, err = io.WriteString(status, m); err != nil { + return + } else if _, err = status.Write([]byte{'\n'}); err != nil { + return + } + } } if errors.Is(err, io.EOF) { err = nil diff --git a/pkg/archive_test.go b/pkg/archive_test.go index 44ea56a7..1ca631ee 100644 --- a/pkg/archive_test.go +++ b/pkg/archive_test.go @@ -202,7 +202,17 @@ func TestArchiveArtifact(t *testing.T) { "checksum/CBPcoVHuVUTVRCMbRl8J30RSSzm_tyfuXaZ-HlZsanY1sY50meOVmgaWDrGKbx9F/devices/uevent": {Mode: 0600, Data: []byte("add")}, "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/-zXKfphyWM2Ko7VMVURaEMSuixNokFSe0xFbnwR2RtRtvMrcPGWalV0LIn45PXTY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CBPcoVHuVUTVRCMbRl8J30RSSzm_tyfuXaZ-HlZsanY1sY50meOVmgaWDrGKbx9F")}, + "identifier/iyvWY0irMoW4AVRnG_du07d_nAEUtbHdeiaAYRdp-vf3wstM9u67IokOsPfU9eyM": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CBPcoVHuVUTVRCMbRl8J30RSSzm_tyfuXaZ-HlZsanY1sY50meOVmgaWDrGKbx9F")}, + + "status": {Mode: fs.ModeDir | 0711}, + "status/iyvWY0irMoW4AVRnG_du07d_nAEUtbHdeiaAYRdp-vf3wstM9u67IokOsPfU9eyM": {Mode: 0444, Data: []byte(statusHeader + `drwx------ block +-rw------- block/uevent (0 bytes) +drwx------ devices +drwx------ devices/empty +drwx------ devices/sub +-rw------- devices/sub/uevent (3 bytes) +-rw------- devices/uevent (3 bytes) +`)}, "substitute": {Mode: fs.ModeDir | 0700}, "work": {Mode: fs.ModeDir | 0700}, diff --git a/pkg/clean_test.go b/pkg/clean_test.go index e31d52aa..3b5d0b3b 100644 --- a/pkg/clean_test.go +++ b/pkg/clean_test.go @@ -52,7 +52,7 @@ func TestClean(t *testing.T) { "lock": {Mode: 0644}, "variant": {Mode: 0400}, - "status": {Mode: fs.ModeDir | 0700}, + "status": {Mode: fs.ModeDir | 0711}, "substitute": {Mode: fs.ModeDir | 0700}, "fault": {Mode: fs.ModeDir | 0700}, "work": {Mode: fs.ModeDir | 0700}, @@ -73,7 +73,7 @@ func TestClean(t *testing.T) { "lock": {Mode: 0644}, "variant": {Mode: 0400}, - "status": {Mode: fs.ModeDir | 0700}, + "status": {Mode: fs.ModeDir | 0711}, "substitute": {Mode: fs.ModeDir | 0700}, "fault": {Mode: fs.ModeDir | 0700}, "work": {Mode: fs.ModeDir | 0700}, @@ -127,7 +127,7 @@ func TestClean(t *testing.T) { "lock": {Mode: 0644}, "variant": {Mode: 0400}, - "status": {Mode: fs.ModeDir | 0700}, + "status": {Mode: fs.ModeDir | 0711}, "substitute": {Mode: fs.ModeDir | 0700}, "substitute/dP-6_wIDRRouOaOF-nkBy-IaUbLdYHbOUTrptu7j_qfW01mnHSjYJ0oykUmvUd2x": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")}, @@ -205,9 +205,9 @@ func TestClean(t *testing.T) { "lock": {Mode: 0644}, "variant": {Mode: 0400}, - "status": {Mode: fs.ModeDir | 0700}, - "status/xxQ43VMIS1WHMSEFnUdBNd6pulbtgiTorP_mtJpEsZENYhGBiDEL6Y2D8yqn0Sra": {Mode: 0400, Data: []byte(statusHeader + "kept")}, - "status/td1tf1kb3z8iUFg2k1xlHeTTEz3xR4e77WSWdv2JhjmZyY6iuvodhdT8BblDOi0E": {Mode: 0400, Data: []byte(statusHeader + "kept")}, + "status": {Mode: fs.ModeDir | 0711}, + "status/xxQ43VMIS1WHMSEFnUdBNd6pulbtgiTorP_mtJpEsZENYhGBiDEL6Y2D8yqn0Sra": {Mode: 0444, Data: []byte(statusHeader + "kept")}, + "status/td1tf1kb3z8iUFg2k1xlHeTTEz3xR4e77WSWdv2JhjmZyY6iuvodhdT8BblDOi0E": {Mode: 0444, Data: []byte(statusHeader + "kept")}, "substitute": {Mode: fs.ModeDir | 0700}, "substitute/td1tf1kb3z8iUFg2k1xlHeTTEz3xR4e77WSWdv2JhjmZyY6iuvodhdT8BblDOi0E": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CyDnDvF-LaeGPcSW70tPosNCoclByWkTjznUUF1DcgzlIwkN9yzz1ZFME1TlPj6W")}, diff --git a/pkg/exec.go b/pkg/exec.go index b40ae84b..fe099ac9 100644 --- a/pkg/exec.go +++ b/pkg/exec.go @@ -601,7 +601,12 @@ func (a *execArtifact) makeContainer( fhs.AbsTmp, std.BindWritable|std.BindEnsure, ) - z.Proc(fhs.AbsProc).Dev(fhs.AbsDev, true) + z. + Proc(fhs.AbsProc). + DevWritable(fhs.AbsDev, true). + Tmpfs(fhs.AbsDevShm, 0, 01777). + Bind(fhs.AbsDevKvm, fhs.AbsDevKvm, std.BindOptional|std.BindDevice). + Remount(fhs.AbsDev, syscall.MS_RDONLY) return } diff --git a/pkg/internal/testtool/main.go b/pkg/internal/testtool/main.go index edffab7e..80f87435 100644 --- a/pkg/internal/testtool/main.go +++ b/pkg/internal/testtool/main.go @@ -259,6 +259,10 @@ func main() { next() } + if m.Next != nil && m.Next.Root == "/kvm" { + next() + } + if m.Next != nil { log.Println("unexpected extra mount entries") for m.Next != nil { @@ -206,7 +206,7 @@ func (t *TContext) prepareStatus(writeHeader bool) error { if t.status, t.statusErr = os.OpenFile( t.statusPath.String(), syscall.O_CREAT|syscall.O_EXCL|syscall.O_WRONLY, - 0400, + 0444, ); t.statusErr != nil { return t.statusErr } @@ -2798,7 +2798,6 @@ func Open( dirSubstitute, dirIdentifier, dirChecksum, - dirStatus, dirFault, dirWork, } { @@ -2810,6 +2809,17 @@ func Open( } } + for _, name := range []string{ + dirStatus, + } { + if err := os.MkdirAll( + base.Append(name).String(), + 0711, + ); err != nil && !errors.Is(err, os.ErrExist) { + return nil, err + } + } + c := Cache{ parent: ctx, diff --git a/pkg/pkg_test.go b/pkg/pkg_test.go index aa5016c1..2d5fdf8e 100644 --- a/pkg/pkg_test.go +++ b/pkg/pkg_test.go @@ -587,7 +587,9 @@ func checkWithCache(t *testing.T, testCases []cacheTestCase) { // destroy empty fault directory if err := os.Remove(base.Append("fault").String()); err != nil { - t.Fatal(err) + if !errors.Is(err, syscall.ENOTEMPTY) { + t.Fatal(err) + } } want := tc.want.hash() @@ -1512,10 +1514,10 @@ func TestCache(t *testing.T) { "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": {Mode: fs.ModeDir | 0711}, "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")}, + "status/heRgWhNJmhm898V68kw0ta76t4rP1o29tYW_TrdyBWXGfo37K3QWA7Z-JkLXAwcn": {Mode: 0444, Data: []byte(statusHeader + "destroyed")}, + "status/dP-6_wIDRRouOaOF-nkBy-IaUbLdYHbOUTrptu7j_qfW01mnHSjYJ0oykUmvUd2x": {Mode: 0444, Data: []byte(statusHeader + "destroyed")}, "substitute": {Mode: fs.ModeDir | 0700}, "substitute/dP-6_wIDRRouOaOF-nkBy-IaUbLdYHbOUTrptu7j_qfW01mnHSjYJ0oykUmvUd2x": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")}, @@ -1610,14 +1612,16 @@ 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/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/9_LKKy-vVT9DxQj-SkqSJFZAc0Yehan3LhldTw8fOIP4XX_DrvkpcPkBV5_46e2q": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, + "identifier/kHH2amyzTN_EpsOyKEOenCROONllTrWAXAwVXOKzx3TgM95-y9ipiz0vkRE-ujBf": {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}, - "status/8VL-egZySw-RbnHZtxGWdf5Z2v9S9CihrdFwa54Bc5EYMQcEgWEem7QrdCTWlCb8": {Mode: 0400, Data: []byte("\x00")}, + "status": {Mode: fs.ModeDir | 0711}, + "status/8VL-egZySw-RbnHZtxGWdf5Z2v9S9CihrdFwa54Bc5EYMQcEgWEem7QrdCTWlCb8": {Mode: 0444, Data: []byte("\x00")}, + "status/9_LKKy-vVT9DxQj-SkqSJFZAc0Yehan3LhldTw8fOIP4XX_DrvkpcPkBV5_46e2q": {Mode: 0444, Data: []byte(statusHeader + "Lrwxrwxrwx result linkname /proc/nonexistent\n")}, + "status/kHH2amyzTN_EpsOyKEOenCROONllTrWAXAwVXOKzx3TgM95-y9ipiz0vkRE-ujBf": {Mode: 0444, Data: []byte(statusHeader)}, "substitute": {Mode: fs.ModeDir | 0700}, "substitute/socGRnhdsJlJ4Z01ZwHFZdLzFH0rWvoaJrylcUKtvhBdGsE7VoYl-vdUuvfK8B4I": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, @@ -1756,17 +1760,19 @@ func TestCache(t *testing.T) { "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/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/9_LKKy-vVT9DxQj-SkqSJFZAc0Yehan3LhldTw8fOIP4XX_DrvkpcPkBV5_46e2q": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, + "identifier/kHH2amyzTN_EpsOyKEOenCROONllTrWAXAwVXOKzx3TgM95-y9ipiz0vkRE-ujBf": {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")}, + "status": {Mode: fs.ModeDir | 0711}, + "status/8VL-egZySw-RbnHZtxGWdf5Z2v9S9CihrdFwa54Bc5EYMQcEgWEem7QrdCTWlCb8": {Mode: 0444, Data: []byte("\x00")}, + "status/9_LKKy-vVT9DxQj-SkqSJFZAc0Yehan3LhldTw8fOIP4XX_DrvkpcPkBV5_46e2q": {Mode: 0444, Data: []byte(statusHeader + "Lrwxrwxrwx result linkname /proc/nonexistent\n")}, + "status/kHH2amyzTN_EpsOyKEOenCROONllTrWAXAwVXOKzx3TgM95-y9ipiz0vkRE-ujBf": {Mode: 0444, Data: []byte(statusHeader)}, "substitute": {Mode: fs.ModeDir | 0700}, - "substitute/socGRnhdsJlJ4Z01ZwHFZdLzFH0rWvoaJrylcUKtvhBdGsE7VoYl-vdUuvfK8B4I": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, "substitute/MccYezQ4pshkeBV4w_aAEIwvZdKHL3OAgAkR3ouZ43EF94Ur1HBHaN7njPfJAj50": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, "substitute/VV5W0_DiA1iylaqbKFThp1ZpV_y1ccVS1XyqDnDaXoHQ-EEyPI4XFrQHcHOF2hWG": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, + "substitute/socGRnhdsJlJ4Z01ZwHFZdLzFH0rWvoaJrylcUKtvhBdGsE7VoYl-vdUuvfK8B4I": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, "work": {Mode: fs.ModeDir | 0700}, }}, @@ -66,6 +66,9 @@ func (a *tarArtifact) Inputs() []Artifact { // IsExclusive returns false: decompressor and tar reader are fully sequential. func (a *tarArtifact) IsExclusive() bool { return false } +// Revision satisfies [RevisionArtifact] for status behaviour. +func (*tarArtifact) Revision() uint64 { return 0 } + // A DisallowedTypeflagError describes a disallowed typeflag encountered while // unpacking a tarball. type DisallowedTypeflagError byte @@ -76,6 +79,11 @@ func (e DisallowedTypeflagError) Error() string { // Cure cures the [Artifact], producing a directory located at work. func (a *tarArtifact) Cure(t *TContext) (err error) { + var status io.Writer + if status, err = t.GetStatusWriter(); err != nil { + return + } + var r io.ReadCloser if r, err = t.Open(a.f); err != nil { return @@ -110,6 +118,7 @@ func (a *tarArtifact) Cure(t *TContext) (err error) { var header *tar.Header tr := tar.NewReader(r) + msg := t.GetMessage() for header, err = tr.Next(); err == nil; header, err = tr.Next() { typeflag := header.Typeflag if typeflag == 0 { @@ -126,6 +135,7 @@ func (a *tarArtifact) Cure(t *TContext) (err error) { } } + var m string switch typeflag { case tar.TypeReg: var f *os.File @@ -142,6 +152,13 @@ func (a *tarArtifact) Cure(t *TContext) (err error) { } else if err = f.Close(); err != nil { return } + + m = fmt.Sprintf( + "%s %s (%d bytes)", + header.FileInfo().Mode(), + header.Name, + header.Size, + ) break case tar.TypeLink: @@ -151,6 +168,13 @@ func (a *tarArtifact) Cure(t *TContext) (err error) { ); err != nil { return } + + m = fmt.Sprintf( + "%s %s linkname %s", + header.FileInfo().Mode(), + header.Name, + header.Linkname, + ) break case tar.TypeSymlink: @@ -160,6 +184,13 @@ func (a *tarArtifact) Cure(t *TContext) (err error) { ); err != nil { return } + + m = fmt.Sprintf( + "%s %s linkname %s", + header.FileInfo().Mode(), + header.Name, + header.Linkname, + ) break case tar.TypeDir: @@ -170,21 +201,37 @@ func (a *tarArtifact) Cure(t *TContext) (err error) { if err = root.MkdirAll(header.Name, 0700); err != nil { return } + + m = fmt.Sprintf( + "%s %s", + header.FileInfo().Mode(), + header.Name, + ) break case tar.TypeChar: - t.GetMessage().Verbosef( - "%sskipping character device %d, %d %q%s", - t.cache.sgrWarn, header.Devmajor, header.Devminor, header.Name, t.cache.sgrRes, + m = fmt.Sprintf( + "skipping character device %d, %d %q", + header.Devmajor, header.Devminor, header.Name, ) - continue + break case tar.TypeXGlobalHeader: - continue // ignore + m = "skipping PAX global key-value record" + break default: return DisallowedTypeflagError(typeflag) } + + if m != "" { + msg.Verbose(m) + if _, err = io.WriteString(status, m); err != nil { + return + } else if _, err = status.Write([]byte{'\n'}); err != nil { + return + } + } } if errors.Is(err, io.EOF) { err = nil diff --git a/pkg/tar_test.go b/pkg/tar_test.go index 5462714f..58ec3aed 100644 --- a/pkg/tar_test.go +++ b/pkg/tar_test.go @@ -44,6 +44,24 @@ func TestTar(t *testing.T) { } wantExpandEncode := pkg.Encode(wantExpand.hash()) + const ( + wantStatus = `drwx------ checksum/ +drwx------ checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/ +-r-------- checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/check (2 bytes) +drwx------ checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/ +Lrwxrwxrwx checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/libedac.so linkname /proc/nonexistent/libedac.so +drwx------ checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/pkgconfig/ +drwx------ identifier/ +Lrwxrwxrwx identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY linkname ../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP +Lrwxrwxrwx identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa linkname ../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP +drwx------ work/ +` + + wantStatusExpand = `drwx------ lib/ +Lrwxrwxrwx lib/libedac.so linkname /proc/nonexistent/libedac.so +` + ) + checkWithCache(t, []cacheTestCase{ {"http", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) { checkTarHTTP(t, base, c, fstest.MapFS{ @@ -79,8 +97,12 @@ func TestTar(t *testing.T) { "checksum/" + wantEncode + "/work": {Mode: fs.ModeDir | 0500}, "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/snWp53xxNdx6cV5KSJqzyVWzLlTsFd8udOisIu8Rgxly09mGcxufYCoQ5CQrHDyZ": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)}, - "identifier/v9DUj2R4YK_3ae0m9VuUYI-HJysDDCENu1k10thxioycRzFH1Qejw5bBGukm4IdL": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)}, + "identifier/82-Dwiovp_DGXPBmnmrTk4XtsduvTBBXxnJTBgyp6avsUhjcqmL9yKQLxkwJJM0x": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)}, + "identifier/ld6DxwiP2Gj47Ue2L_pFv6NrOth8nkU5W1voMyivd2aVROrorGqPlpbyHUnU1AvI": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)}, + + "status": {Mode: fs.ModeDir | 0711}, + "status/82-Dwiovp_DGXPBmnmrTk4XtsduvTBBXxnJTBgyp6avsUhjcqmL9yKQLxkwJJM0x": {Mode: 0444, Data: []byte(statusHeader + wantStatus)}, + "status/ld6DxwiP2Gj47Ue2L_pFv6NrOth8nkU5W1voMyivd2aVROrorGqPlpbyHUnU1AvI": {Mode: 0444, Data: []byte(statusHeader + wantStatus)}, "substitute": {Mode: fs.ModeDir | 0700}, @@ -103,8 +125,12 @@ func TestTar(t *testing.T) { "checksum/" + wantExpandEncode + "/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")}, "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/1SuvgGltcsgqps9tWqjULG8RCdpx_6KVWXdsMd5xPKvdtysOxqpE-3bLu4j0WpGk": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)}, - "identifier/snWp53xxNdx6cV5KSJqzyVWzLlTsFd8udOisIu8Rgxly09mGcxufYCoQ5CQrHDyZ": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)}, + "identifier/82-Dwiovp_DGXPBmnmrTk4XtsduvTBBXxnJTBgyp6avsUhjcqmL9yKQLxkwJJM0x": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)}, + "identifier/fsMFOV4_LoYWbC8GNqL2zjbpzNzT80vPWbSw4L47caKVIta333WIW2TZXoSW8ntH": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)}, + + "status": {Mode: fs.ModeDir | 0711}, + "status/82-Dwiovp_DGXPBmnmrTk4XtsduvTBBXxnJTBgyp6avsUhjcqmL9yKQLxkwJJM0x": {Mode: 0444, Data: []byte(statusHeader + wantStatusExpand)}, + "status/fsMFOV4_LoYWbC8GNqL2zjbpzNzT80vPWbSw4L47caKVIta333WIW2TZXoSW8ntH": {Mode: 0444, Data: []byte(statusHeader + wantStatusExpand)}, "substitute": {Mode: fs.ModeDir | 0700}, @@ -206,13 +232,13 @@ func checkTarHTTP( {"directory", pkg.NewTar(&tarDir), ignorePathname, want, pkg.WNew, nil}, - {"multiple entries", pkg.NewTar(&tarDirMulti), nil, nil, pkg.WNew, errors.New( + {"multiple entries", pkg.NewTar(&tarDirMulti), nil, nil, pkg.WNew, errors.Join(errors.New( "input directory does not contain a single regular file", - )}, + ))}, - {"bad type", pkg.NewTar(&tarDirType), nil, nil, pkg.WNew, errors.New( + {"bad type", pkg.NewTar(&tarDirType), nil, nil, pkg.WNew, errors.Join(errors.New( "input directory does not contain a single regular file", - )}, + ))}, {"error passthrough", pkg.NewTar(&stubArtifact{ kind: pkg.KindExec, @@ -220,6 +246,13 @@ func checkTarHTTP( cure: func(t *pkg.TContext) error { return stub.UniqueError(0xcafe) }, - }), nil, nil, pkg.WNew, stub.UniqueError(0xcafe)}, + }), nil, nil, pkg.WNew, errors.Join(stub.UniqueError(0xcafe))}, }) + + fault := base.Append("fault") + if err := os.RemoveAll(fault.String()); err != nil { + t.Fatal(err) + } else if err = os.Mkdir(fault.String(), 0); err != nil { + t.Fatal(err) + } } |
