File: group.go

package info (click to toggle)
singularity-container 4.0.3%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 21,672 kB
  • sloc: asm: 3,857; sh: 2,125; ansic: 1,677; awk: 414; makefile: 110; python: 99
file content (94 lines) | stat: -rw-r--r-- 2,576 bytes parent folder | download | duplicates (2)
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
}