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
diff --git a/cmd/soong_zip/soong_zip.go b/cmd/soong_zip/soong_zip.go
index cbec102..ef436a9 100644
--- a/cmd/soong_zip/soong_zip.go
+++ b/cmd/soong_zip/soong_zip.go
@@ -365,7 +365,10 @@
 				currentWriter, err = zipw.CreateCompressedHeader(op.fh)
 			} else {
 				var zw io.Writer
-				zw, err = zipw.CreateHeader(op.fh)
+
+				op.fh.CompressedSize64 = op.fh.UncompressedSize64
+
+				zw, err = zipw.CreateHeaderAndroid(op.fh)
 				currentWriter = nopCloser{zw}
 			}
 			if err != nil {
diff --git a/third_party/zip/android.go b/third_party/zip/android.go
index f3b6055..bde3afa 100644
--- a/third_party/zip/android.go
+++ b/third_party/zip/android.go
@@ -19,6 +19,8 @@
 	"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 @@
 	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 @@
 		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 @@
 	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 3a9292e..4c5eb78 100644
--- a/third_party/zip/writer.go
+++ b/third_party/zip/writer.go
@@ -192,6 +192,15 @@
 	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 @@
 // 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 @@
 		// 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 @@
 	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 @@
 	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 @@
 		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)
+	// 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)
 	}
-	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)
+	// END ANDROID CHANGE
 	return err
 }