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 }