aboutsummaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/archive.go42
-rw-r--r--pkg/archive_test.go12
-rw-r--r--pkg/clean_test.go12
-rw-r--r--pkg/exec.go7
-rw-r--r--pkg/internal/testtool/main.go4
-rw-r--r--pkg/pkg.go14
-rw-r--r--pkg/pkg_test.go32
-rw-r--r--pkg/tar.go57
-rw-r--r--pkg/tar_test.go51
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 {
diff --git a/pkg/pkg.go b/pkg/pkg.go
index 75e0d1b1..e3d32028 100644
--- a/pkg/pkg.go
+++ b/pkg/pkg.go
@@ -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},
}},
diff --git a/pkg/tar.go b/pkg/tar.go
index 9a8c4b76..33952b05 100644
--- a/pkg/tar.go
+++ b/pkg/tar.go
@@ -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)
+ }
}