mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
95 lines
2.0 KiB
Go
95 lines
2.0 KiB
Go
package dpkg
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
|
|
"github.com/anchore/imgbom/imgbom/pkg"
|
|
"github.com/mitchellh/mapstructure"
|
|
)
|
|
|
|
var endOfPackages = fmt.Errorf("no more packages to read")
|
|
|
|
func ParseEntries(reader io.Reader) ([]pkg.DpkgMetadata, error) {
|
|
buffedReader := bufio.NewReader(reader)
|
|
var entries = make([]pkg.DpkgMetadata, 0)
|
|
|
|
for {
|
|
entry, err := parseEntry(buffedReader)
|
|
if err != nil {
|
|
if err == endOfPackages {
|
|
break
|
|
}
|
|
return nil, err
|
|
}
|
|
entries = append(entries, entry)
|
|
}
|
|
|
|
return entries, nil
|
|
}
|
|
|
|
func parseEntry(reader *bufio.Reader) (entry pkg.DpkgMetadata, err error) {
|
|
dpkgFields := make(map[string]string)
|
|
var key string
|
|
|
|
for {
|
|
line, err := reader.ReadString('\n')
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
return pkg.DpkgMetadata{}, endOfPackages
|
|
}
|
|
return pkg.DpkgMetadata{}, err
|
|
}
|
|
|
|
line = strings.TrimRight(line, "\n")
|
|
|
|
// empty line indicates end of entry
|
|
if len(line) == 0 {
|
|
// if the entry has not started, keep parsing lines
|
|
if len(dpkgFields) == 0 {
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
|
|
switch {
|
|
case strings.HasPrefix(line, " "):
|
|
// a field-body continuation
|
|
if len(key) == 0 {
|
|
return pkg.DpkgMetadata{}, fmt.Errorf("no match for continuation: line: '%s'", line)
|
|
}
|
|
|
|
val, ok := dpkgFields[key]
|
|
if !ok {
|
|
return pkg.DpkgMetadata{}, fmt.Errorf("no previous key exists, expecting: %s", key)
|
|
}
|
|
// concatenate onto previous value
|
|
val = fmt.Sprintf("%s\n %s", val, strings.TrimSpace(line))
|
|
dpkgFields[key] = val
|
|
default:
|
|
// parse a new key
|
|
if i := strings.Index(line, ":"); i > 0 {
|
|
key = strings.TrimSpace(line[0:i])
|
|
val := strings.TrimSpace(line[i+1:])
|
|
|
|
if _, ok := dpkgFields[key]; ok {
|
|
return pkg.DpkgMetadata{}, fmt.Errorf("duplicate key discovered: %s", key)
|
|
}
|
|
|
|
dpkgFields[key] = val
|
|
} else {
|
|
return pkg.DpkgMetadata{}, fmt.Errorf("cannot parse field from line: '%s'", line)
|
|
}
|
|
}
|
|
}
|
|
|
|
err = mapstructure.Decode(dpkgFields, &entry)
|
|
if err != nil {
|
|
return pkg.DpkgMetadata{}, err
|
|
}
|
|
|
|
return entry, nil
|
|
}
|