debconf: implement dat file parser
This commit is contained in:
parent
0b91c379b8
commit
053e07c319
92
debconf/debconf.go
Normal file
92
debconf/debconf.go
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
package debconf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DefaultConfigDat = `/var/cache/debconf/config.dat`
|
||||||
|
DefaultPasswordsDat = `/var/cache/debconf/passwords.dat`
|
||||||
|
DefaultTemplatesDat = `/var/cache/debconf/templates.dat`
|
||||||
|
)
|
||||||
|
|
||||||
|
type Entry struct {
|
||||||
|
Name string
|
||||||
|
Properties [][2]string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Database struct {
|
||||||
|
Entries []Entry
|
||||||
|
AllColumnNames []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(r io.Reader) (*Database, error) {
|
||||||
|
sc := bufio.NewScanner(r)
|
||||||
|
|
||||||
|
var entries []Entry
|
||||||
|
var wip Entry
|
||||||
|
var linenum int = 0
|
||||||
|
|
||||||
|
knownColumnNames := map[string]struct{}{
|
||||||
|
"Name": struct{}{},
|
||||||
|
}
|
||||||
|
var discoveredColumns []string
|
||||||
|
|
||||||
|
for sc.Scan() {
|
||||||
|
linenum++
|
||||||
|
line := sc.Text()
|
||||||
|
|
||||||
|
if line == "" {
|
||||||
|
if wip.Name != "" {
|
||||||
|
entries = append(entries, wip)
|
||||||
|
wip = Entry{}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if line[0] == ' ' {
|
||||||
|
// continuation of last text entry
|
||||||
|
if len(wip.Properties) == 0 {
|
||||||
|
return nil, fmt.Errorf("Continuation of nonexistent entry on line %d", linenum)
|
||||||
|
}
|
||||||
|
|
||||||
|
wip.Properties[len(wip.Properties)-1][1] += line[1:]
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// New pair on current element
|
||||||
|
key, rest, ok := strings.Cut(line, `:`)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("Missing : on line %d", linenum)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := knownColumnNames[key]; !ok {
|
||||||
|
knownColumnNames[key] = struct{}{}
|
||||||
|
discoveredColumns = append(discoveredColumns, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
if key == `Name` {
|
||||||
|
wip.Name = rest
|
||||||
|
} else {
|
||||||
|
wip.Properties = append(wip.Properties, [2]string{key, rest})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if sc.Err() != nil {
|
||||||
|
return nil, sc.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
if wip.Name != "" {
|
||||||
|
entries = append(entries, wip)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Database{
|
||||||
|
Entries: entries,
|
||||||
|
AllColumnNames: discoveredColumns,
|
||||||
|
}, nil
|
||||||
|
}
|
30
debconf/debconf_test.go
Normal file
30
debconf/debconf_test.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package debconf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDebconfParse(t *testing.T) {
|
||||||
|
src, err := os.Open(DefaultConfigDat)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
t.Skip(err)
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
|
||||||
|
db, err := Parse(src)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(db.Entries) == 0 {
|
||||||
|
t.Errorf("expected >0 entries, got %v", len(db.Entries))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(db.AllColumnNames) == 0 {
|
||||||
|
t.Errorf("expected >0 column names, got %v", len(db.AllColumnNames))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user