github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/cmds/core/id/groups.go (about) 1 // Copyright 2017-2018 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build !plan9 6 7 package main 8 9 import ( 10 "bufio" 11 "fmt" 12 "os" 13 "strconv" 14 "strings" 15 ) 16 17 // Groups manages a group database, typically loaded from /etc/group 18 type Groups struct { 19 gidToGroup map[int]string 20 groupToGID map[string]int 21 userToGIDs map[string][]int 22 gidToUsers map[int][]string 23 } 24 25 // GetGID returns the GID of a group 26 func (g *Groups) GetGID(name string) (int, error) { 27 if v, ok := g.groupToGID[name]; ok { 28 return v, nil 29 } 30 return -1, fmt.Errorf("unknown group name: %s", name) 31 } 32 33 // GetGroup gets the group of a GID 34 func (g *Groups) GetGroup(gid int) (string, error) { 35 if v, ok := g.gidToGroup[gid]; ok { 36 return v, nil 37 } 38 return "", fmt.Errorf("unknown gid: %d", gid) 39 } 40 41 // UserGetGIDs returns a slice of GIDs for a username 42 func (g *Groups) UserGetGIDs(username string) []int { 43 if v, ok := g.userToGIDs[username]; ok { 44 return v 45 } 46 return nil 47 } 48 49 // NewGroups reads the GroupFile for groups. 50 // It assumes the format "name:passwd:number:groupList". 51 func NewGroups(file string) (g *Groups, e error) { 52 g = &Groups{} 53 54 g.gidToGroup = make(map[int]string) 55 g.groupToGID = make(map[string]int) 56 g.gidToUsers = make(map[int][]string) 57 g.userToGIDs = make(map[string][]int) 58 59 groupFile, err := os.Open(file) 60 if err != nil { 61 return g, err 62 } 63 64 var groupInfo []string 65 66 groupScanner := bufio.NewScanner(groupFile) 67 68 for groupScanner.Scan() { 69 txt := groupScanner.Text() 70 if len(txt) == 0 || txt[0] == '#' { // skip empty lines and comments 71 continue 72 } 73 groupInfo = strings.Split(txt, ":") 74 groupNum, err := strconv.Atoi(groupInfo[2]) 75 if err != nil { 76 return nil, err 77 } 78 79 g.gidToGroup[groupNum] = groupInfo[0] 80 g.groupToGID[groupInfo[0]] = groupNum 81 82 users := strings.Split(groupInfo[3], ",") 83 for _, u := range users { 84 g.userToGIDs[u] = append(g.userToGIDs[u], groupNum) 85 g.gidToUsers[groupNum] = append(g.gidToUsers[groupNum], u) 86 } 87 } 88 89 return 90 }