Files
go-dpkg/apt/sum.go
Matheus Sampaio Queiroga 8498030b4f
All checks were successful
Golang test / go-test (push) Successful in 23s
Update Packege http error message
Signed-off-by: Matheus Sampaio Queiroga <srherobrine20@gmail.com>
2025-06-22 22:28:16 -03:00

125 lines
3.3 KiB
Go

package apt
import (
"fmt"
"io"
"iter"
"net/http"
"net/url"
"path"
"strconv"
"strings"
"sirherobrine23.com.br/sirherobrine23/go-dpkg/deb822"
"sirherobrine23.com.br/sirherobrine23/go-dpkg/dpkg"
"sirherobrine23.com.br/sirherobrine23/go-dpkg/internal/descompress"
)
// ReleaseSum represents a mapping from a string key (such as a file name or section name)
// to a slice of Sum values, where each Sum contains checksum information for the corresponding entry.
// This is typically used to store and organize checksums for files listed in an APT Release file.
type ReleaseSum map[string][]Sum
// Files sum from Release
type Sum struct {
File string
Hash string
Size int64
}
// SumLines parses a string containing multiple checksum lines (typically from a Debian Release file)
// and returns a ReleaseSum map containing the parsed sums. Each line is expected to contain a hash, a size,
// and a filename, separated by spaces. The function splits each line, extracts the hash, size, and file name,
// and appends the result to the ReleaseSum map keyed by the file name without its extension.
// Returns an error if any size value cannot be parsed as an integer.
func SumLines(data string) (ReleaseSum, error) {
sums := ReleaseSum{}
for name := range deb822.ToSlice(data) {
hash := name[:strings.Index(name, " ")]
name = strings.TrimSpace(name[len(hash):])
sizeStr := name[:strings.Index(name, " ")]
name = strings.TrimSpace(name[len(sizeStr):])
size, err := strconv.ParseInt(sizeStr, 10, 64)
if err != nil {
return nil, err
}
ext := path.Ext(name)
mapText := name[:len(name)-len(ext)]
sums[mapText] = append(sums[mapText], Sum{
Hash: hash,
Size: size,
File: name,
})
}
return sums, nil
}
func (sum Sum) IsBinaryPackage() bool {
if strings.ToLower(path.Base(sum.File[:len(sum.File)-len(path.Ext(sum.File))])) == "packages" {
nodes := strings.Split(sum.File, "/")
if len(nodes) == 3 && strings.HasPrefix(nodes[1], "binary-") {
return true
}
}
return false
}
// Return packages from sum file
func (sum Sum) Pkgs(SuiteName string, AptSrc *AptSource) iter.Seq2[*dpkg.Package, error] {
return func(yield func(*dpkg.Package, error) bool) {
if !sum.IsBinaryPackage() {
yield(nil, fmt.Errorf("this sum require have Package last element"))
return
}
r, metaIndex, metaURI := io.Reader(nil), 0, (*url.URL)(nil)
for metaIndex, metaURI = range AptSrc.URIs {
metaURI = metaURI.ResolveReference(&url.URL{Path: path.Join(metaURI.Path, "dists", SuiteName, sum.File)})
res, err := http.Get(metaURI.String())
if err != nil {
yield(nil, err)
return
} else if res.StatusCode != 200 {
if metaIndex == len(AptSrc.URIs)-1 {
yield(nil, (*HttpError)(res))
return
}
continue
}
defer res.Body.Close()
if r, err = descompress.Descompress(res.Body); err != nil {
yield(nil, fmt.Errorf("cannot descompress body: %s", err))
return
}
}
if metaURI == nil {
yield(nil, fmt.Errorf("cannot get Packages file"))
return
}
pkgReader := deb822.NewReader(r)
for {
pkgData, err := pkgReader.Deb822()
switch err {
case deb822.ErrNextDeb822:
continue
case io.EOF:
return
case nil:
pkg := &dpkg.Package{}
err = pkg.FromMap(pkgData)
if !yield(pkg, err) {
return
}
default:
yield(nil, err)
return
}
}
}
}