Merge "Support writing a ZIP64 file header"
This commit is contained in:
commit
cef48e956b
|
@ -74,3 +74,69 @@ func TestStripZip64Extras(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCopyFromZip64(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("slow test; skipping")
|
||||||
|
}
|
||||||
|
|
||||||
|
const size = uint32max + 1
|
||||||
|
fromZipBytes := &bytes.Buffer{}
|
||||||
|
fromZip := NewWriter(fromZipBytes)
|
||||||
|
w, err := fromZip.CreateHeaderAndroid(&FileHeader{
|
||||||
|
Name: "large",
|
||||||
|
Method: Store,
|
||||||
|
UncompressedSize64: size,
|
||||||
|
CompressedSize64: size,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Create: %v", err)
|
||||||
|
}
|
||||||
|
_, err = w.Write(make([]byte, size))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Write: %v", err)
|
||||||
|
}
|
||||||
|
err = fromZip.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Close: %v", err)
|
||||||
|
}
|
||||||
|
fromZip = nil
|
||||||
|
|
||||||
|
fromZipReader, err := NewReader(bytes.NewReader(fromZipBytes.Bytes()), int64(fromZipBytes.Len()))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewReader: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
toZipBytes := &bytes.Buffer{}
|
||||||
|
toZip := NewWriter(toZipBytes)
|
||||||
|
err = toZip.CopyFrom(fromZipReader.File[0], fromZipReader.File[0].Name)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CopyFrom: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = toZip.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Close: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save some memory
|
||||||
|
fromZipReader = nil
|
||||||
|
fromZipBytes.Reset()
|
||||||
|
|
||||||
|
toZipReader, err := NewReader(bytes.NewReader(toZipBytes.Bytes()), int64(toZipBytes.Len()))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewReader: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(toZipReader.File) != 1 {
|
||||||
|
t.Fatalf("Expected 1 file in toZip, got %d", len(toZipReader.File))
|
||||||
|
}
|
||||||
|
|
||||||
|
if g, w := toZipReader.File[0].CompressedSize64, uint64(size); g != w {
|
||||||
|
t.Errorf("Expected CompressedSize64 %d, got %d", w, g)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g, w := toZipReader.File[0].UncompressedSize64, uint64(size); g != w {
|
||||||
|
t.Errorf("Expected UnompressedSize64 %d, got %d", w, g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -276,9 +276,6 @@ func writeHeader(w io.Writer, h *FileHeader) error {
|
||||||
} else {
|
} else {
|
||||||
b.uint32(h.CRC32)
|
b.uint32(h.CRC32)
|
||||||
|
|
||||||
if h.CompressedSize64 > uint32max || h.UncompressedSize64 > uint32max {
|
|
||||||
panic("skipping writing the data descriptor for a 64-bit value is not yet supported")
|
|
||||||
}
|
|
||||||
compressedSize := uint32(h.CompressedSize64)
|
compressedSize := uint32(h.CompressedSize64)
|
||||||
if compressedSize == 0 {
|
if compressedSize == 0 {
|
||||||
compressedSize = h.CompressedSize
|
compressedSize = h.CompressedSize
|
||||||
|
@ -289,6 +286,21 @@ func writeHeader(w io.Writer, h *FileHeader) error {
|
||||||
uncompressedSize = h.UncompressedSize
|
uncompressedSize = h.UncompressedSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if h.CompressedSize64 > uint32max || h.UncompressedSize64 > uint32max {
|
||||||
|
// Sizes don't fit in a 32-bit field, put them in a zip64 extra instead.
|
||||||
|
compressedSize = uint32max
|
||||||
|
uncompressedSize = uint32max
|
||||||
|
|
||||||
|
// append a zip64 extra block to Extra
|
||||||
|
var buf [20]byte // 2x uint16 + 2x uint64
|
||||||
|
eb := writeBuf(buf[:])
|
||||||
|
eb.uint16(zip64ExtraId)
|
||||||
|
eb.uint16(16) // size = 2x uint64
|
||||||
|
eb.uint64(h.UncompressedSize64)
|
||||||
|
eb.uint64(h.CompressedSize64)
|
||||||
|
h.Extra = append(h.Extra, buf[:]...)
|
||||||
|
}
|
||||||
|
|
||||||
b.uint32(compressedSize)
|
b.uint32(compressedSize)
|
||||||
b.uint32(uncompressedSize)
|
b.uint32(uncompressedSize)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue