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