package deb import ( "fmt" "github.com/smira/aptly/utils" "io/ioutil" "os" "path/filepath" ) // Changes is a result of .changes file parsing type Changes struct { Changes string Distribution string Files PackageFiles BasePath, ChangesName string TempDir string Stanza Stanza } func NewChanges(path string) (*Changes, error) { var err error c := &Changes{ BasePath: filepath.Dir(path), ChangesName: filepath.Base(path), } c.TempDir, err = ioutil.TempDir(os.TempDir(), "aptly") if err != nil { return nil, err } // copy .changes file into temporary directory err = utils.CopyFile(filepath.Join(c.BasePath, c.ChangesName), filepath.Join(c.TempDir, c.ChangesName)) if err != nil { return nil, err } return c, nil } // VerifyAndParse does optional signature verification and parses changes files func (c *Changes) VerifyAndParse(acceptUnsigned, ignoreSignature bool, verifier utils.Verifier) error { input, err := os.Open(filepath.Join(c.TempDir, c.ChangesName)) if err != nil { return err } defer input.Close() isClearSigned, err := verifier.IsClearSigned(input) if err != nil { return err } input.Seek(0, 0) if !isClearSigned && !acceptUnsigned { return fmt.Errorf(".changes file is not signed and unsigned processing hasn't been enabled") } if isClearSigned && !ignoreSignature { err = verifier.VerifyClearsigned(input) if err != nil { return err } input.Seek(0, 0) } var text *os.File if isClearSigned { text, err = verifier.ExtractClearsigned(input) if err != nil { return err } defer text.Close() } else { text = input } reader := NewControlFileReader(text) c.Stanza, err = reader.ReadStanza() if err != nil { return err } c.Distribution = c.Stanza["Distribution"] c.Changes = c.Stanza["Changes"] c.Files, err = c.Files.ParseSumFields(c.Stanza) if err != nil { return err } return nil } // Prepare creates temporary directory, copies file there and verifies checksums func (c *Changes) Prepare() error { var err error for _, file := range c.Files { if filepath.Dir(file.Filename) != "." { return fmt.Errorf("file is not in the same folder as .changes file: %s", file.Filename) } file.Filename = filepath.Base(file.Filename) err = utils.CopyFile(filepath.Join(c.BasePath, file.Filename), filepath.Join(c.TempDir, file.Filename)) if err != nil { return err } } for _, file := range c.Files { var info utils.ChecksumInfo info, err = utils.ChecksumsForFile(filepath.Join(c.TempDir, file.Filename)) if err != nil { return err } if info.MD5 != file.Checksums.MD5 { return fmt.Errorf("checksum mismatch MD5: expected %v != obtained %v", file.Checksums.MD5, info.MD5) } if info.SHA1 != file.Checksums.SHA1 { return fmt.Errorf("checksum mismatch SHA1: expected %v != obtained %v", file.Checksums.SHA1, info.SHA1) } if info.SHA256 != file.Checksums.SHA256 { return fmt.Errorf("checksum mismatch SHA256 expected %v != obtained %v", file.Checksums.SHA256, info.SHA256) } } return nil } // Cleanup removes all temporary files func (c *Changes) Cleanup() error { if c.TempDir == "" { return nil } return os.RemoveAll(c.TempDir) }