github.com/apptainer/singularity@v3.1.1+incompatible/internal/pkg/util/fs/files/group.go (about)

     1  // Copyright (c) 2018, Sylabs Inc. All rights reserved.
     2  // This software is licensed under a 3-clause BSD license. Please consult the
     3  // LICENSE.md file distributed with the sources of this project regarding your
     4  // rights to use or distribute this software.
     5  
     6  package files
     7  
     8  import (
     9  	"fmt"
    10  	"io/ioutil"
    11  	"os"
    12  
    13  	"github.com/sylabs/singularity/internal/pkg/sylog"
    14  	"github.com/sylabs/singularity/internal/pkg/util/fs"
    15  	"github.com/sylabs/singularity/internal/pkg/util/user"
    16  )
    17  
    18  // Group creates a group template based on content of file provided in path,
    19  // updates content with current user information and returns content
    20  func Group(path string, uid int, gids []int) (content []byte, err error) {
    21  	duplicate := false
    22  	groups := make([]int, 0)
    23  
    24  	sylog.Verbosef("Checking for template group file: %s\n", path)
    25  	if fs.IsFile(path) == false {
    26  		return content, fmt.Errorf("group file doesn't exist in container, not updating")
    27  	}
    28  
    29  	sylog.Verbosef("Creating group content\n")
    30  	groupFile, err := os.Open(path)
    31  	if err != nil {
    32  		return content, fmt.Errorf("failed to open group file in container: %s", err)
    33  	}
    34  	defer groupFile.Close()
    35  
    36  	pwInfo, err := user.GetPwUID(uint32(uid))
    37  	if err != nil || pwInfo == nil {
    38  		return content, err
    39  	}
    40  	if len(gids) == 0 {
    41  		grInfo, err := user.GetGrGID(pwInfo.GID)
    42  		if err != nil || grInfo == nil {
    43  			return content, err
    44  		}
    45  		groups, err = os.Getgroups()
    46  		if err != nil {
    47  			return content, err
    48  		}
    49  	} else {
    50  		groups = gids
    51  	}
    52  	for _, gid := range groups {
    53  		if gid == int(pwInfo.GID) {
    54  			duplicate = true
    55  			break
    56  		}
    57  	}
    58  	if duplicate == false {
    59  		if len(gids) == 0 {
    60  			groups = append(groups, int(pwInfo.GID))
    61  		}
    62  	}
    63  	content, err = ioutil.ReadAll(groupFile)
    64  	if err != nil {
    65  		return content, fmt.Errorf("failed to read group file content in container: %s", err)
    66  	}
    67  
    68  	if len(content) > 0 && content[len(content)-1] != '\n' {
    69  		content = append(content, '\n')
    70  	}
    71  
    72  	for _, gid := range groups {
    73  		grInfo, err := user.GetGrGID(uint32(gid))
    74  		if err != nil || grInfo == nil {
    75  			sylog.Verbosef("Skipping GID %d as group entry doesn't exist.\n", gid)
    76  			continue
    77  		}
    78  		groupLine := fmt.Sprintf("%s:x:%d:%s\n", grInfo.Name, grInfo.GID, pwInfo.Name)
    79  		content = append(content, []byte(groupLine)...)
    80  	}
    81  	return content, nil
    82  }