Source file
src/os/user/listgroups_unix.go
1
2
3
4
5
6
7 package user
8
9 import (
10 "bufio"
11 "bytes"
12 "errors"
13 "fmt"
14 "io"
15 "os"
16 "strconv"
17 )
18
19 func listGroupsFromReader(u *User, r io.Reader) ([]string, error) {
20 if u.Username == "" {
21 return nil, errors.New("user: list groups: empty username")
22 }
23 primaryGid, err := strconv.Atoi(u.Gid)
24 if err != nil {
25 return nil, fmt.Errorf("user: list groups for %s: invalid gid %q", u.Username, u.Gid)
26 }
27
28 userCommas := []byte("," + u.Username + ",")
29 userFirst := userCommas[1:]
30 userLast := userCommas[:len(userCommas)-1]
31 userOnly := userCommas[1 : len(userCommas)-1]
32
33
34 groups := []string{u.Gid}
35
36 rd := bufio.NewReader(r)
37 done := false
38 for !done {
39 line, err := rd.ReadBytes('\n')
40 if err != nil {
41 if err == io.EOF {
42 done = true
43 } else {
44 return groups, err
45 }
46 }
47
48
49
50
51
52
53
54 line = bytes.TrimSpace(line)
55 if len(line) == 0 || line[0] == '#' ||
56
57
58
59 line[0] == '+' || line[0] == '-' {
60 continue
61 }
62
63
64
65
66
67
68 listIdx := bytes.LastIndexByte(line, ':')
69 if listIdx == -1 || listIdx == len(line)-1 {
70
71 continue
72 }
73 if bytes.Count(line[:listIdx], colon) != 2 {
74
75 continue
76 }
77 list := line[listIdx+1:]
78
79 if !(bytes.Equal(list, userOnly) || bytes.HasPrefix(list, userFirst) || bytes.HasSuffix(list, userLast) || bytes.Contains(list, userCommas)) {
80 continue
81 }
82
83
84 parts := bytes.Split(line[:listIdx], colon)
85 if len(parts) != 3 || len(parts[0]) == 0 {
86 continue
87 }
88 gid := string(parts[2])
89
90 numGid, err := strconv.Atoi(gid)
91 if err != nil || numGid == primaryGid {
92 continue
93 }
94
95 groups = append(groups, gid)
96 }
97
98 return groups, nil
99 }
100
101 func listGroups(u *User) ([]string, error) {
102 f, err := os.Open(groupFile)
103 if err != nil {
104 return nil, err
105 }
106 defer f.Close()
107
108 return listGroupsFromReader(u, f)
109 }
110
View as plain text