lib/suitar: let WriteHeader write a directory entry WriteHeader copied h into w.header before calling w.Write to emit the GNUTYPE_LONGNAME block holding the name. Write only accepts TypeReg and TypeGNUSparse, so a TypeDir header failed that call and left the Writer permanently in an error state - every later entry on the same Writer failed too. Set w.header after the name block has gone out instead.
diff --git a/lib/suitar/suitar.go b/lib/suitar/suitar.go index 9da6a16..3a6212c 100644 --- a/lib/suitar/suitar.go +++ b/lib/suitar/suitar.go
@@ -322,10 +322,8 @@ w.err = errBadHeader return w.err } - w.header = *h - - n := len(w.header.Name) - copy(w.nameBuf[:], w.header.Name) + n := len(h.Name) + copy(w.nameBuf[:], h.Name) w.nameBuf[n] = 0 initBlock(&w.block, typeGNULongName, int64(n+1), Mode644, 0) @@ -334,6 +332,10 @@ return w.err } + // The w.Write call below writes this entry's name, not its contents, so + // w.header must not (yet) say TypeDir or Write would reject it. Set + // w.header after that call. + w.header = Header{Typeflag: TypeReg} w.remaining = int64(n + 1) if _, err := w.Write(w.nameBuf[:n+1]); err != nil { @@ -344,6 +346,7 @@ return w.err } + w.header = *h initBlock(&w.block, w.header.Typeflag, w.header.Size, w.header.Mode, w.header.ModTime.Unix()) if _, err := w.w.Write(w.block[:]); err != nil { w.err = err