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