diff --git a/deb/deb.go b/deb/deb.go index 2a31125c..d8e1e579 100644 --- a/deb/deb.go +++ b/deb/deb.go @@ -2,12 +2,16 @@ package deb import ( "archive/tar" + "compress/bzip2" "compress/gzip" "fmt" "github.com/mkrautz/goar" + "github.com/remyoudompheng/go-liblzma" "github.com/smira/aptly/utils" + "github.com/smira/lzma" "io" "os" + "strings" ) // GetControlFileFromDeb reads control file from deb package @@ -95,3 +99,76 @@ func GetControlFileFromDsc(dscFile string, verifier utils.Verifier) (Stanza, err return stanza, nil } + +// GetContentsFromDeb returns list of files installed by .deb package +func GetContentsFromDeb(packageFile string) ([]string, error) { + file, err := os.Open(packageFile) + if err != nil { + return nil, err + } + defer file.Close() + + library := ar.NewReader(file) + for { + header, err := library.Next() + if err == io.EOF { + return nil, fmt.Errorf("unable to find data.tar.* part") + } + if err != nil { + return nil, fmt.Errorf("unable to read .deb archive: %s", err) + } + + if strings.HasPrefix(header.Name, "data.tar") { + var tarInput io.Reader + + fmt.Println(header.Name) + switch header.Name { + case "data.tar": + tarInput = library + case "data.tar.gz": + ungzip, err := gzip.NewReader(library) + if err != nil { + return nil, fmt.Errorf("unable to ungzip: %s", err) + } + defer ungzip.Close() + tarInput = ungzip + case "data.tar.bz2": + tarInput = bzip2.NewReader(library) + case "data.tar.xz": + unxz, err := xz.NewReader(library) + if err != nil { + return nil, fmt.Errorf("unable to unxz: %s", err) + } + defer unxz.Close() + tarInput = unxz + case "data.tar.lzma": + unlzma := lzma.NewReader(library) + defer unlzma.Close() + tarInput = unlzma + default: + return nil, fmt.Errorf("unsupported tar compression: %s", header.Name) + } + + untar := tar.NewReader(tarInput) + var results []string + for { + tarHeader, err := untar.Next() + if err == io.EOF { + return results, nil + } + if err != nil { + return nil, fmt.Errorf("unable to read .tar archive: %s", err) + } + + if tarHeader.Typeflag == tar.TypeDir { + continue + } + + if strings.HasPrefix(tarHeader.Name, "./") { + tarHeader.Name = tarHeader.Name[2:] + } + results = append(results, tarHeader.Name) + } + } + } +} diff --git a/deb/deb_test.go b/deb/deb_test.go index 4c329c04..a069699c 100644 --- a/deb/deb_test.go +++ b/deb/deb_test.go @@ -9,7 +9,7 @@ import ( ) type DebSuite struct { - debFile, dscFile, dscFileNoSign string + debFile, debFile2, dscFile, dscFileNoSign string } var _ = Suite(&DebSuite{}) @@ -17,6 +17,7 @@ var _ = Suite(&DebSuite{}) 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.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") } @@ -55,3 +56,15 @@ func (s *DebSuite) TestGetControlFileFromDsc(c *C) { c.Check(st["Version"], Equals, "0.6.1-1.4") c.Check(st["Source"], Equals, "pyspi") } + +func (s *DebSuite) TestGetContentsFromDeb(c *C) { + contents, err := GetContentsFromDeb(s.debFile) + c.Check(err, IsNil) + c.Check(contents, DeepEquals, []string{"usr/share/doc/libboost-program-options-dev/changelog.gz", + "usr/share/doc/libboost-program-options-dev/copyright"}) + + contents, err = GetContentsFromDeb(s.debFile2) + c.Check(err, IsNil) + c.Check(contents, DeepEquals, []string{"usr/bin/hardlink", "usr/share/man/man1/hardlink.1.gz", + "usr/share/doc/hardlink/changelog.gz", "usr/share/doc/hardlink/copyright", "usr/share/doc/hardlink/NEWS.Debian.gz"}) +}