gitlab.com/apertussolutions/u-root@v7.0.0+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  }