mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-01-12 03:21:33 +00:00
Only small amount of required checks is enabled, plan is to enable more linters as issues are fixed in the code.
151 lines
3.5 KiB
Go
151 lines
3.5 KiB
Go
package deb
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"hash/fnv"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/smira/aptly/aptly"
|
|
"github.com/smira/aptly/utils"
|
|
)
|
|
|
|
// PackageFile is a single file entry in package
|
|
type PackageFile struct {
|
|
// Filename is name of file for the package (without directory)
|
|
Filename string
|
|
// Hashes for the file
|
|
Checksums utils.ChecksumInfo
|
|
// Temporary field used while downloading, stored relative path on the mirror
|
|
downloadPath string
|
|
}
|
|
|
|
// Verify that package file is present and correct
|
|
func (f *PackageFile) Verify(packagePool aptly.PackagePool) (bool, error) {
|
|
poolPath, err := packagePool.Path(f.Filename, f.Checksums.MD5)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
st, err := os.Stat(poolPath)
|
|
if err != nil {
|
|
return false, nil
|
|
}
|
|
|
|
// verify size
|
|
// TODO: verify checksum if configured
|
|
return st.Size() == f.Checksums.Size, nil
|
|
}
|
|
|
|
// DownloadURL return relative URL to package download location
|
|
func (f *PackageFile) DownloadURL() string {
|
|
return filepath.Join(f.downloadPath, f.Filename)
|
|
}
|
|
|
|
// PackageFiles is collection of package files
|
|
type PackageFiles []PackageFile
|
|
|
|
// Hash compute hash of all file items, sorting them first
|
|
func (files PackageFiles) Hash() uint64 {
|
|
sort.Sort(files)
|
|
|
|
h := fnv.New64a()
|
|
|
|
for _, f := range files {
|
|
h.Write([]byte(f.Filename))
|
|
binary.Write(h, binary.BigEndian, f.Checksums.Size)
|
|
h.Write([]byte(f.Checksums.MD5))
|
|
h.Write([]byte(f.Checksums.SHA1))
|
|
h.Write([]byte(f.Checksums.SHA256))
|
|
}
|
|
|
|
return h.Sum64()
|
|
}
|
|
|
|
// Len returns number of files
|
|
func (files PackageFiles) Len() int {
|
|
return len(files)
|
|
}
|
|
|
|
// Swap swaps elements
|
|
func (files PackageFiles) Swap(i, j int) {
|
|
files[i], files[j] = files[j], files[i]
|
|
}
|
|
|
|
// Less compares by filename
|
|
func (files PackageFiles) Less(i, j int) bool {
|
|
return files[i].Filename < files[j].Filename
|
|
}
|
|
|
|
func (files PackageFiles) parseSumField(input string, setter func(sum *utils.ChecksumInfo, data string)) (PackageFiles, error) {
|
|
for _, line := range strings.Split(input, "\n") {
|
|
line = strings.TrimSpace(line)
|
|
if line == "" {
|
|
continue
|
|
}
|
|
parts := strings.Fields(line)
|
|
|
|
if len(parts) < 3 {
|
|
return nil, fmt.Errorf("unparseable hash sum line: %#v", line)
|
|
}
|
|
|
|
size, err := strconv.ParseInt(parts[1], 10, 64)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to parse size: %s", err)
|
|
}
|
|
|
|
filename := filepath.Base(parts[len(parts)-1])
|
|
|
|
found := false
|
|
pos := 0
|
|
for i, file := range files {
|
|
if file.Filename == filename {
|
|
found = true
|
|
pos = i
|
|
break
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
files = append(files, PackageFile{Filename: filename})
|
|
pos = len(files) - 1
|
|
}
|
|
|
|
files[pos].Checksums.Size = size
|
|
setter(&files[pos].Checksums, parts[0])
|
|
}
|
|
|
|
return files, nil
|
|
}
|
|
|
|
// ParseSumFields populates PackageFiles by parsing stanza checksums fields
|
|
func (files PackageFiles) ParseSumFields(stanza Stanza) (PackageFiles, error) {
|
|
var err error
|
|
|
|
files, err = files.parseSumField(stanza["Files"], func(sum *utils.ChecksumInfo, data string) { sum.MD5 = data })
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
files, err = files.parseSumField(stanza["Checksums-Sha1"], func(sum *utils.ChecksumInfo, data string) { sum.SHA1 = data })
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
files, err = files.parseSumField(stanza["Checksums-Sha256"], func(sum *utils.ChecksumInfo, data string) { sum.SHA256 = data })
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
files, err = files.parseSumField(stanza["Checksums-Sha512"], func(sum *utils.ChecksumInfo, data string) { sum.SHA512 = data })
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return files, nil
|
|
}
|