...

Source file src/github.com/containerd/continuity/groups_unix.go

Documentation: github.com/containerd/continuity

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  //nolint:unused,deadcode
    18  package continuity
    19  
    20  import (
    21  	"bufio"
    22  	"fmt"
    23  	"io"
    24  	"os"
    25  	"strconv"
    26  	"strings"
    27  )
    28  
    29  // TODO(stevvooe): This needs a lot of work before we can call it useful.
    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  // parseGroups parses an /etc/group file for group names, ids and membership.
    93  // This is unix specific.
    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 // skip comment
   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