diff options
author | Jeff Gaston <jeffrygaston@google.com> | 2017-08-24 14:11:27 -0700 |
---|---|---|
committer | Jeff Gaston <jeffrygaston@google.com> | 2017-08-24 14:43:35 -0700 |
commit | c5eb66d16b82279d33746d312e91793970e0310f (patch) | |
tree | 087757782b42ab20087265365536545b8a1a0d4b /third_party | |
parent | 6dd56e0f4a2614590064290016984a7d1cb574c6 (diff) | |
download | build_soong-c5eb66d16b82279d33746d312e91793970e0310f.tar.gz build_soong-c5eb66d16b82279d33746d312e91793970e0310f.tar.bz2 build_soong-c5eb66d16b82279d33746d312e91793970e0310f.zip |
Have soong_zip not write a data descriptor for non-compressed files
Bug: 64536066
Test: m -j blueprint_tools && cd /tmp && mkdir zip && \
cd zip && touch empty-file && \
echo empty-file > files.list && \
soong_zip -o zip.zip -C . -l files.list && \
jar -xvf zip.zip && echo ok
Change-Id: Iac5797aab5282237fa1cc902e6b068a7937c012a
Diffstat (limited to 'third_party')
-rw-r--r-- | third_party/zip/android.go | 17 | ||||
-rw-r--r-- | third_party/zip/writer.go | 99 |
2 files changed, 85 insertions, 31 deletions
diff --git a/third_party/zip/android.go b/third_party/zip/android.go index f3b60555..bde3afa4 100644 --- a/third_party/zip/android.go +++ b/third_party/zip/android.go @@ -19,6 +19,8 @@ import ( "io" ) +const DataDescriptorFlag = 0x8 + func (w *Writer) CopyFrom(orig *File, newName string) error { if w.last != nil && !w.last.closed { if err := w.last.close(); err != nil { @@ -30,7 +32,7 @@ func (w *Writer) CopyFrom(orig *File, newName string) error { fileHeader := orig.FileHeader fileHeader.Name = newName fh := &fileHeader - fh.Flags |= 0x8 + fh.Flags |= DataDescriptorFlag // The zip64 extras change between the Central Directory and Local File Header, while we use // the same structure for both. The Local File Haeder is taken care of by us writing a data @@ -122,7 +124,7 @@ func (w *Writer) CreateCompressedHeader(fh *FileHeader) (io.WriteCloser, error) return nil, errors.New("archive/zip: invalid duplicate FileHeader") } - fh.Flags |= 0x8 // we will write a data descriptor + fh.Flags |= DataDescriptorFlag // we will write a data descriptor fh.CreatorVersion = fh.CreatorVersion&0xff00 | zipVersion20 // preserve compatibility byte fh.ReaderVersion = zipVersion20 @@ -149,6 +151,17 @@ func (w *Writer) CreateCompressedHeader(fh *FileHeader) (io.WriteCloser, error) return fw, nil } +// Updated version of CreateHeader that doesn't enforce writing a data descriptor +func (w *Writer) CreateHeaderAndroid(fh *FileHeader) (io.Writer, error) { + writeDataDescriptor := fh.Method != Store + if writeDataDescriptor { + fh.Flags &= DataDescriptorFlag + } else { + fh.Flags &= ^uint16(DataDescriptorFlag) + } + return w.createHeaderImpl(fh) +} + type compressedFileWriter struct { fileWriter } diff --git a/third_party/zip/writer.go b/third_party/zip/writer.go index 3a9292e3..4c5eb78b 100644 --- a/third_party/zip/writer.go +++ b/third_party/zip/writer.go @@ -192,6 +192,15 @@ func (w *Writer) Create(name string) (io.Writer, error) { return w.CreateHeader(header) } +// BEGIN ANDROID CHANGE separate createHeaderImpl from CreateHeader +// Legacy version of CreateHeader +func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) { + fh.Flags |= DataDescriptorFlag // writing a data descriptor + return w.createHeaderImpl(fh) +} + +// END ANDROID CHANGE + // CreateHeader adds a file to the zip file using the provided FileHeader // for the file metadata. // It returns a Writer to which the file contents should be written. @@ -199,7 +208,10 @@ func (w *Writer) Create(name string) (io.Writer, error) { // The file's contents must be written to the io.Writer before the next // call to Create, CreateHeader, or Close. The provided FileHeader fh // must not be modified after a call to CreateHeader. -func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) { + +// BEGIN ANDROID CHANGE separate createHeaderImpl from CreateHeader +func (w *Writer) createHeaderImpl(fh *FileHeader) (io.Writer, error) { + // END ANDROID CHANGE if w.last != nil && !w.last.closed { if err := w.last.close(); err != nil { return nil, err @@ -209,9 +221,9 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) { // See https://golang.org/issue/11144 confusion. return nil, errors.New("archive/zip: invalid duplicate FileHeader") } - - fh.Flags |= 0x8 // we will write a data descriptor - + // BEGIN ANDROID CHANGE move the setting of DataDescriptorFlag into CreateHeader + // fh.Flags |= 0x8 // we will write a data descriptor + // END ANDROID CHANGE fh.CreatorVersion = fh.CreatorVersion&0xff00 | zipVersion20 // preserve compatibility byte fh.ReaderVersion = zipVersion20 @@ -255,9 +267,32 @@ func writeHeader(w io.Writer, h *FileHeader) error { b.uint16(h.Method) b.uint16(h.ModifiedTime) b.uint16(h.ModifiedDate) - b.uint32(0) // since we are writing a data descriptor crc32, - b.uint32(0) // compressed size, - b.uint32(0) // and uncompressed size should be zero + // BEGIN ANDROID CHANGE populate header size fields and crc field if not writing a data descriptor + if h.Flags&DataDescriptorFlag != 0 { + // since we are writing a data descriptor, these fields should be 0 + b.uint32(0) // crc32, + b.uint32(0) // compressed size, + b.uint32(0) // uncompressed size + } else { + 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) + if compressedSize == 0 { + compressedSize = h.CompressedSize + } + + uncompressedSize := uint32(h.UncompressedSize64) + if uncompressedSize == 0 { + uncompressedSize = h.UncompressedSize + } + + b.uint32(compressedSize) + b.uint32(uncompressedSize) + } + // END ANDROID CHANGE b.uint16(uint16(len(h.Name))) b.uint16(uint16(len(h.Extra))) if _, err := w.Write(buf[:]); err != nil { @@ -306,7 +341,9 @@ func (w *fileWriter) Write(p []byte) (int, error) { return w.rawCount.Write(p) } -func (w *fileWriter) close() error { +// BEGIN ANDROID CHANGE give the return value a name +func (w *fileWriter) close() (err error) { + // END ANDROID CHANGE if w.closed { return errors.New("zip: file closed twice") } @@ -330,28 +367,32 @@ func (w *fileWriter) close() error { fh.UncompressedSize = uint32(fh.UncompressedSize64) } - // Write data descriptor. This is more complicated than one would - // think, see e.g. comments in zipfile.c:putextended() and - // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7073588. - // The approach here is to write 8 byte sizes if needed without - // adding a zip64 extra in the local header (too late anyway). - var buf []byte - if fh.isZip64() { - buf = make([]byte, dataDescriptor64Len) - } else { - buf = make([]byte, dataDescriptorLen) - } - b := writeBuf(buf) - b.uint32(dataDescriptorSignature) // de-facto standard, required by OS X - b.uint32(fh.CRC32) - if fh.isZip64() { - b.uint64(fh.CompressedSize64) - b.uint64(fh.UncompressedSize64) - } else { - b.uint32(fh.CompressedSize) - b.uint32(fh.UncompressedSize) + // BEGIN ANDROID CHANGE only write data descriptor if the flag is set + if fh.Flags&DataDescriptorFlag != 0 { + // Write data descriptor. This is more complicated than one would + // think, see e.g. comments in zipfile.c:putextended() and + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7073588. + // The approach here is to write 8 byte sizes if needed without + // adding a zip64 extra in the local header (too late anyway). + var buf []byte + if fh.isZip64() { + buf = make([]byte, dataDescriptor64Len) + } else { + buf = make([]byte, dataDescriptorLen) + } + b := writeBuf(buf) + b.uint32(dataDescriptorSignature) // de-facto standard, required by OS X + b.uint32(fh.CRC32) + if fh.isZip64() { + b.uint64(fh.CompressedSize64) + b.uint64(fh.UncompressedSize64) + } else { + b.uint32(fh.CompressedSize) + b.uint32(fh.UncompressedSize) + } + _, err = w.zipw.Write(buf) } - _, err := w.zipw.Write(buf) + // END ANDROID CHANGE return err } |