Skip to content

Commit

Permalink
Add dpkg support (#7)
Browse files Browse the repository at this point in the history
This PR adds several data structures and memo methods
to support parsing dpkginfo oval structures.

Signed-off-by: louis <[email protected]>

Co-authored-by: louis <[email protected]>
  • Loading branch information
Louis DeLosSantos and louis authored Aug 11, 2020
1 parent 1ff8552 commit 08a0863
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 34 deletions.
49 changes: 49 additions & 0 deletions oval/dpkginfo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package oval

import (
"encoding/xml"
)

// DpkgInfoTest : >tests>dpkginfo_test
type DpkgInfoTest struct {
XMLName xml.Name `xml:"dpkginfo_test"`
ID string `xml:"id,attr"`
Comment string `xml:"comment,attr"`
Check string `xml:"check,attr"`
Version int `xml:"version,attr"`
ObjectRefs []ObjectRef `xml:"object"`
StateRefs []StateRef `xml:"state"`
}

// DpkgName : >objects>dpkginfo_object>name
//
// when parsing ubuntu var_ref is a reference
// to the <variables> section of the document
//
// when parsing debian var_ref is empty and
// the Body field is used directly
type DpkgName struct {
XMLName xml.Name `xml:"name"`
Ref string `xml:"var_ref,attr"`
Body string `xml:",chardata"`
}

// DpkgInfoObject : >objects>dpkginfo_object
type DpkgInfoObject struct {
XMLName xml.Name `xml:"dpkginfo_object"`
ID string `xml:"id,attr"`
Version int `xml:"version,attr"`
Name *DpkgName `xml:"name"`
}

// DpkgInfoState : >states>dpkginfo_state
type DpkgInfoState struct {
XMLName xml.Name `xml:"dpkginfo_state"`
ID string `xml:"id,attr"`
Version int `xml:"version,attr"`
Arch *Arch `xml:"arch"`
Epoch *Epoch `xml:"epoch"`
Release *Release `xml:"release"`
DpkgVersion *Version `xml:"version"`
EVR *EVR `xml:"evr"`
}
14 changes: 12 additions & 2 deletions oval/objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

func (o *Objects) init() {
var wg sync.WaitGroup
wg.Add(3)
wg.Add(4)

go func() {
defer wg.Done()
Expand All @@ -33,6 +33,14 @@ func (o *Objects) init() {
}
}()

go func() {
defer wg.Done()
o.dpkginfoMemo = make(map[string]int, len(o.DpkgInfoObjects))
for i, v := range o.DpkgInfoObjects {
o.dpkginfoMemo[v.ID] = i
}
}()

wg.Wait()
}

Expand All @@ -43,13 +51,15 @@ func (o *Objects) Lookup(ref string) (kind string, index int, err error) {
if i, ok := o.lineMemo[ref]; ok {
return o.LineObjects[i].XMLName.Local, i, nil
}

if i, ok := o.version55Memo[ref]; ok {
return o.Version55Objects[i].XMLName.Local, i, nil
}
if i, ok := o.rpminfoMemo[ref]; ok {
return o.RPMInfoObjects[i].XMLName.Local, i, nil
}
if i, ok := o.dpkginfoMemo[ref]; ok {
return o.DpkgInfoObjects[i].XMLName.Local, i, nil
}

// We didn't find it, maybe we can say why.
id, err := ParseID(ref)
Expand Down
35 changes: 5 additions & 30 deletions oval/rpminfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,39 +39,14 @@ type RPMInfoState struct {
XMLName xml.Name `xml:"rpminfo_state"`
ID string `xml:"id,attr"`
Version int `xml:"version,attr"`
Arch *RPMArch `xml:"arch"`
Epoch *RPMEpoch `xml:"epoch"`
Release *RPMRelease `xml:"release"`
RPMVersion *RPMVersion `xml:"version"`
EVR *RPMEVR `xml:"evr"`
Arch *Arch `xml:"arch"`
Epoch *Epoch `xml:"epoch"`
Release *Release `xml:"release"`
RPMVersion *Version `xml:"version"`
EVR *EVR `xml:"evr"`
SignatureKeyID *RPMSignatureKeyID `xml:"signature_keyid"`
}

type RPMArch struct {
XMLName xml.Name `xml:"arch"`
Operation Operation `xml:"operation,attr"`
Body string `xml:",chardata"`
}
type RPMEpoch struct {
XMLName xml.Name `xml:"epoch"`
Operation Operation `xml:"operation,attr"`
Body string `xml:",chardata"`
}
type RPMRelease struct {
XMLName xml.Name `xml:"release"`
Operation Operation `xml:"operation,attr"`
Body string `xml:",chardata"`
}
type RPMVersion struct {
XMLName xml.Name `xml:"version"`
Operation Operation `xml:"operation,attr"`
Body string `xml:",chardata"`
}
type RPMEVR struct {
XMLName xml.Name `xml:"evr"`
Operation Operation `xml:"operation,attr"`
Body string `xml:",chardata"`
}
type RPMSignatureKeyID struct {
XMLName xml.Name `xml:"signature_keyid"`
Operation Operation `xml:"operation,attr"`
Expand Down
13 changes: 12 additions & 1 deletion oval/states.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

func (s *States) init() {
var wg sync.WaitGroup
wg.Add(3)
wg.Add(4)

go func() {
defer wg.Done()
Expand All @@ -33,6 +33,14 @@ func (s *States) init() {
}
}()

go func() {
defer wg.Done()
s.dpkginfoMemo = make(map[string]int, len(s.DpkgInfoStates))
for i, v := range s.DpkgInfoStates {
s.dpkginfoMemo[v.ID] = i
}
}()

wg.Wait()
}

Expand All @@ -50,6 +58,9 @@ func (s *States) Lookup(ref string) (kind string, index int, err error) {
if i, ok := s.rpminfoMemo[ref]; ok {
return s.RPMInfoStates[i].XMLName.Local, i, nil
}
if i, ok := s.dpkginfoMemo[ref]; ok {
return s.DpkgInfoStates[i].XMLName.Local, i, nil
}

// We didn't find it, maybe we can say why.
id, err := ParseID(ref)
Expand Down
13 changes: 12 additions & 1 deletion oval/tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
// Init sets up the memoization maps.
func (t *Tests) init() {
var wg sync.WaitGroup
wg.Add(6)
wg.Add(7)

go func() {
defer wg.Done()
Expand All @@ -34,6 +34,14 @@ func (t *Tests) init() {
}
}()

go func() {
defer wg.Done()
t.dpkginfoMemo = make(map[string]int, len(t.DpkgInfoTests))
for i, v := range t.DpkgInfoTests {
t.dpkginfoMemo[v.ID] = i
}
}()

go func() {
defer wg.Done()
t.rpmverifyfileMemo = make(map[string]int, len(t.RPMVerifyFileTests))
Expand Down Expand Up @@ -76,6 +84,9 @@ func (t *Tests) Lookup(ref string) (kind string, index int, err error) {
if i, ok := t.rpminfoMemo[ref]; ok {
return t.RPMInfoTests[i].XMLName.Local, i, nil
}
if i, ok := t.dpkginfoMemo[ref]; ok {
return t.DpkgInfoTests[i].XMLName.Local, i, nil
}
if i, ok := t.rpmverifyfileMemo[ref]; ok {
return t.RPMVerifyFileTests[i].XMLName.Local, i, nil
}
Expand Down
66 changes: 66 additions & 0 deletions oval/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Root struct {
Tests Tests `xml:"tests"`
Objects Objects `xml:"objects"`
States States `xml:"states"`
Variables Variables `xml:"variables"`
}

// Generator : >generator
Expand Down Expand Up @@ -229,12 +230,14 @@ type Tests struct {
LineTests []LineTest `xml:"line_test"`
Version55Tests []Version55Test `xml:"version55_test"`
RPMInfoTests []RPMInfoTest `xml:"rpminfo_test"`
DpkgInfoTests []DpkgInfoTest `xml:"dpkginfo_test"`
RPMVerifyFileTests []RPMVerifyFileTest `xml:"rpmverifyfile_test"`
UnameTests []UnameTest `xml:"uname_test"`
TextfileContent54Tests []TextfileContent54Test `xml:"textfilecontent54_test"`
lineMemo map[string]int
version55Memo map[string]int
rpminfoMemo map[string]int
dpkginfoMemo map[string]int
rpmverifyfileMemo map[string]int
unameMemo map[string]int
textfilecontent54Memo map[string]int
Expand All @@ -261,9 +264,11 @@ type Objects struct {
LineObjects []LineObject `xml:"line_object"`
Version55Objects []Version55Object `xml:"version55_object"`
RPMInfoObjects []RPMInfoObject `xml:"rpminfo_object"`
DpkgInfoObjects []DpkgInfoObject `xml:"dpkginfo_object"`
lineMemo map[string]int
version55Memo map[string]int
rpminfoMemo map[string]int
dpkginfoMemo map[string]int
}

// States : >states
Expand All @@ -273,7 +278,68 @@ type States struct {
LineStates []LineState `xml:"line_state"`
Version55States []Version55State `xml:"version55_state"`
RPMInfoStates []RPMInfoState `xml:"rpminfo_state"`
DpkgInfoStates []DpkgInfoState `xml:"dpkginfo_state"`
lineMemo map[string]int
version55Memo map[string]int
rpminfoMemo map[string]int
dpkginfoMemo map[string]int
}

// Value
type Value struct {
XMLName xml.Name `xml:"value"`
Body string `xml:",chardata"`
}

// ConstantVariable
type ConstantVariable struct {
XMLName xml.Name `xml:"constant_variable"`
ID string `xml:"id,attr"`
Version string `xml:"version,attr"`
Datatype string `xml:"datatype,attr"`
Comment string `xml:"comment,attr"`
Values []Value `xml:"value"`
}

// Variables : >variables
type Variables struct {
once sync.Once
XMLName xml.Name `xml:"variables"`
ConstantVariables []ConstantVariable `xml:"constant_variable"`
dpkginfoMemo map[string]int
}

// Arch
type Arch struct {
XMLName xml.Name `xml:"arch"`
Operation Operation `xml:"operation,attr"`
Body string `xml:",chardata"`
}

// Epoch
type Epoch struct {
XMLName xml.Name `xml:"epoch"`
Operation Operation `xml:"operation,attr"`
Body string `xml:",chardata"`
}

// Release
type Release struct {
XMLName xml.Name `xml:"release"`
Operation Operation `xml:"operation,attr"`
Body string `xml:",chardata"`
}

// Version
type Version struct {
XMLName xml.Name `xml:"version"`
Operation Operation `xml:"operation,attr"`
Body string `xml:",chardata"`
}

// EVR
type EVR struct {
XMLName xml.Name `xml:"evr"`
Operation Operation `xml:"operation,attr"`
Body string `xml:",chardata"`
}
40 changes: 40 additions & 0 deletions oval/variables.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package oval

import (
"fmt"
"sync"
)

func (o *Variables) init() {
var wg sync.WaitGroup
wg.Add(1)

go func() {
defer wg.Done()
o.dpkginfoMemo = make(map[string]int, len(o.ConstantVariables))
for i, v := range o.ConstantVariables {
o.dpkginfoMemo[v.ID] = i
}
}()

wg.Wait()
}

// Lookup returns the kind of object and index into that kind-specific slice, if
// found.
func (o *Variables) Lookup(ref string) (kind string, index int, err error) {
o.once.Do(o.init)
if i, ok := o.dpkginfoMemo[ref]; ok {
return o.ConstantVariables[i].XMLName.Local, i, nil
}

// We didn't find it, maybe we can say why.
id, err := ParseID(ref)
if err != nil {
return "", -1, err
}
if id.Type != OvalVariable {
return "", -1, fmt.Errorf("oval: wrong identifier type %q", id.Type)
}
return "", -1, ErrNotFound(ref)
}

0 comments on commit 08a0863

Please sign in to comment.