From: Harald Sitter <sitter@kde.org>
Date: Tue, 31 Oct 2017 11:36:31 +0100
Subject: make deb reader handle new control.tar options introduced in dpkg
 1.17.6

newly supported is uncompressed control.tar and xz compressed
control.tar.xz. latter is used by ubuntu for dbgsym ddebs.

Fixes #655
---
 deb/deb.go                                         |  39 +++++++++++++++++----
 deb/deb_test.go                                    |  11 +++++-
 ...sym_5.9.1+dfsg-2+18.04+bionic+build4_amd64.ddeb | Bin 0 -> 972 bytes
 3 files changed, 42 insertions(+), 8 deletions(-)
 create mode 100644 system/changes/libqt5concurrent5-dbgsym_5.9.1+dfsg-2+18.04+bionic+build4_amd64.ddeb

diff --git a/deb/deb.go b/deb/deb.go
index 50c7b7c..757155f 100644
--- a/deb/deb.go
+++ b/deb/deb.go
@@ -29,21 +29,46 @@ func GetControlFileFromDeb(packageFile string) (Stanza, error) {
 	library := ar.NewReader(file)
 	for {
 		header, err := library.Next()
+
 		if err == io.EOF {
-			return nil, fmt.Errorf("unable to find control.tar.gz part in package %s", packageFile)
+			return nil, fmt.Errorf("unable to find control.tar.* part in package %s", packageFile)
 		}
 		if err != nil {
 			return nil, fmt.Errorf("unable to read .deb archive %s: %s", packageFile, err)
 		}
 
-		if header.Name == "control.tar.gz" {
-			ungzip, err := gzip.NewReader(library)
-			if err != nil {
-				return nil, fmt.Errorf("unable to ungzip control file from %s. Error: %s", packageFile, err)
+		// As per deb(5) version 1.19.0.4 the control file may be:
+		// - control.tar (since 1.17.6)
+		// - control.tar.gz
+		// - control.tar.xz (since 1.17.6)
+		// Look for all of the above and uncompress as necessary.
+		if strings.HasPrefix(header.Name, "control.tar") {
+			bufReader := bufio.NewReader(library)
+
+			var tarInput io.Reader
+
+			switch header.Name {
+			case "control.tar":
+				tarInput = bufReader
+			case "control.tar.gz":
+				ungzip, err := gzip.NewReader(bufReader)
+				if err != nil {
+					return nil, fmt.Errorf("unable to ungzip %s from %s", header.Name, packageFile)
+				}
+				defer ungzip.Close()
+				tarInput = ungzip
+			case "control.tar.xz":
+				unxz, err := xz.NewReader(bufReader)
+				if err != nil {
+					return nil, fmt.Errorf("unable to unxz %s from %s", header.Name, packageFile)
+				}
+				defer unxz.Close()
+				tarInput = unxz
+			default:
+				return nil, fmt.Errorf("unsupported tar compression in %s: %s", packageFile, header.Name)
 			}
-			defer ungzip.Close()
 
-			untar := tar.NewReader(ungzip)
+			untar := tar.NewReader(tarInput)
 			for {
 				tarHeader, err := untar.Next()
 				if err == io.EOF {
diff --git a/deb/deb_test.go b/deb/deb_test.go
index 0260044..bd4e680 100644
--- a/deb/deb_test.go
+++ b/deb/deb_test.go
@@ -10,7 +10,7 @@ import (
 )
 
 type DebSuite struct {
-	debFile, debFile2, dscFile, dscFileNoSign string
+	debFile, debFile2, debFileWithXzControl, dscFile, dscFileNoSign string
 }
 
 var _ = Suite(&DebSuite{})
@@ -19,6 +19,7 @@ func (s *DebSuite) SetUpSuite(c *C) {
 	_, _File, _, _ := runtime.Caller(0)
 	s.debFile = filepath.Join(filepath.Dir(_File), "../system/files/libboost-program-options-dev_1.49.0.1_i386.deb")
 	s.debFile2 = filepath.Join(filepath.Dir(_File), "../system/changes/hardlink_0.2.1_amd64.deb")
+	s.debFileWithXzControl = filepath.Join(filepath.Dir(_File), "../system/changes/libqt5concurrent5-dbgsym_5.9.1+dfsg-2+18.04+bionic+build4_amd64.ddeb")
 	s.dscFile = filepath.Join(filepath.Dir(_File), "../system/files/pyspi_0.6.1-1.3.dsc")
 	s.dscFileNoSign = filepath.Join(filepath.Dir(_File), "../system/files/pyspi-0.6.1-1.3.stripped.dsc")
 }
@@ -37,6 +38,14 @@ func (s *DebSuite) TestGetControlFileFromDeb(c *C) {
 	c.Check(st["Package"], Equals, "libboost-program-options-dev")
 }
 
+func (s *DebSuite) TestGetControlFileFromDebWithXzControl(c *C) {
+	// Has control.tar.xz archive inside.
+	st, err := GetControlFileFromDeb(s.debFileWithXzControl)
+	c.Check(err, IsNil)
+	c.Check(st["Version"], Equals, "5.9.1+dfsg-2+18.04+bionic+build4")
+	c.Check(st["Package"], Equals, "libqt5concurrent5-dbgsym")
+}
+
 func (s *DebSuite) TestGetControlFileFromDsc(c *C) {
 	verifier := &utils.GpgVerifier{}
 
diff --git a/system/changes/libqt5concurrent5-dbgsym_5.9.1+dfsg-2+18.04+bionic+build4_amd64.ddeb b/system/changes/libqt5concurrent5-dbgsym_5.9.1+dfsg-2+18.04+bionic+build4_amd64.ddeb
new file mode 100644
index 0000000..77d6946
--- /dev/null
+++ b/system/changes/libqt5concurrent5-dbgsym_5.9.1+dfsg-2+18.04+bionic+build4_amd64.ddeb
@@ -0,0 +1,6 @@
+!<arch>
+debian-binary   1509443940  0     0     100644  4         `
+2.0
+control.tar.xz  1509443940  0     0     100644  600       `
+�7zXZ�ִF!t/��'�]�}��JF���.���_���!���}ݯ����͆D���C�2✗����!�ؿ��1�~&1�����]y)#ٖ1�ϺH�����:�N)�H��_�_&�������g!b-�\;�� ��Kg�%s��Fe��ێe2�=�)jL�5��?��b��,�XT~I�vѕ��|�I��3���C�L�Q✈OŇ�$���l�mJ��"��m��l�-���E&&%�����P��H��V�9���q��'�֍:ȯ8�5�(D�V�ܓIm�����T���x|�N%Z�@~^Nu�w%��TNDl�c-��[��U�.U��-e�%��RO��%����G�u�+F���V&[Ie1`�B�>���z�Ė8virL9��B�GJ�c�
��� �(�Oٵō�Mxte�ޓ�"���+�n��6@u��	�i���Dy�g����*�2	&&͔=ت,#��/� �T��9��R�]јL�"�����\�~2c��?߷�B(;�Ɠ�5�	:_�����7�Bt�̕+0�K���PF*�f��g�YZdata.tar.xz     1509443940  0     0     100644  180       `
+�7zXZ�ִF!t/��'�r]�}��JF���.���_���!�_��P<�r�MxLp�����H��Uc�M������fS�Q�l�Y������MU}��3`r�F�/WeOݕ��B=)�;�y֜Zh�I;
-�-�%��PNj[��g�YZ
\ No newline at end of file
