...
1
16
17
18 package continuity
19
20 import (
21 "bufio"
22 "fmt"
23 "io"
24 "os"
25 "strconv"
26 "strings"
27 )
28
29
30
31 type groupIndex struct {
32 byName map[string]*group
33 byGID map[int]*group
34 }
35
36 func getGroupIndex() (*groupIndex, error) {
37 f, err := os.Open("/etc/group")
38 if err != nil {
39 return nil, err
40 }
41 defer f.Close()
42
43 groups, err := parseGroups(f)
44 if err != nil {
45 return nil, err
46 }
47
48 return newGroupIndex(groups), nil
49 }
50
51 func newGroupIndex(groups []group) *groupIndex {
52 gi := &groupIndex{
53 byName: make(map[string]*group),
54 byGID: make(map[int]*group),
55 }
56
57 for i, group := range groups {
58 gi.byGID[group.gid] = &groups[i]
59 gi.byName[group.name] = &groups[i]
60 }
61
62 return gi
63 }
64
65 type group struct {
66 name string
67 gid int
68 members []string
69 }
70
71 func getGroupName(gid int) (string, error) {
72 f, err := os.Open("/etc/group")
73 if err != nil {
74 return "", err
75 }
76 defer f.Close()
77
78 groups, err := parseGroups(f)
79 if err != nil {
80 return "", err
81 }
82
83 for _, group := range groups {
84 if group.gid == gid {
85 return group.name, nil
86 }
87 }
88
89 return "", fmt.Errorf("no group for gid")
90 }
91
92
93
94 func parseGroups(rd io.Reader) ([]group, error) {
95 var groups []group
96 scanner := bufio.NewScanner(rd)
97
98 for scanner.Scan() {
99 if strings.HasPrefix(scanner.Text(), "#") {
100 continue
101 }
102
103 parts := strings.SplitN(scanner.Text(), ":", 4)
104
105 if len(parts) != 4 {
106 return nil, fmt.Errorf("bad entry: %q", scanner.Text())
107 }
108
109 name, _, sgid, smembers := parts[0], parts[1], parts[2], parts[3]
110
111 gid, err := strconv.Atoi(sgid)
112 if err != nil {
113 return nil, fmt.Errorf("bad gid: %q", gid)
114 }
115
116 members := strings.Split(smembers, ",")
117
118 groups = append(groups, group{
119 name: name,
120 gid: gid,
121 members: members,
122 })
123 }
124
125 if scanner.Err() != nil {
126 return nil, scanner.Err()
127 }
128
129 return groups, nil
130 }
131
View as plain text