File: idtools.go

package info (click to toggle)
rootlesskit 2.0.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie, trixie-proposed-updates
  • size: 636 kB
  • sloc: sh: 433; makefile: 25
file content (83 lines) | stat: -rw-r--r-- 2,368 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
// Package idtools is forked from https://github.com/moby/moby/tree/298ba5b13150bfffe8414922a951a7a793276d31/pkg/idtools
package idtools

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

type SubIDRange struct {
	Start  int
	Length int
}

const (
	subuidFileName = "/etc/subuid"
	subgidFileName = "/etc/subgid"
)

func GetSubIDRanges(uid int, username string) ([]SubIDRange, []SubIDRange, error) {
	subuidRanges, err := parseSubuid(uid, username)
	if err != nil {
		return nil, nil, err
	}
	subgidRanges, err := parseSubgid(uid, username)
	if err != nil {
		return nil, nil, err
	}
	if len(subuidRanges) == 0 {
		return nil, nil, fmt.Errorf("No subuid ranges found for user %d (%q)", uid, username)
	}
	if len(subgidRanges) == 0 {
		return nil, nil, fmt.Errorf("No subgid ranges found for user %d (%q)", uid, username)
	}
	return subuidRanges, subgidRanges, nil
}

func parseSubuid(uid int, username string) ([]SubIDRange, error) {
	return parseSubidFile(subuidFileName, uid, username)
}

func parseSubgid(uid int, username string) ([]SubIDRange, error) {
	return parseSubidFile(subgidFileName, uid, username)
}

// parseSubidFile will read the appropriate file (/etc/subuid or /etc/subgid)
// and return all found ranges for a specified user. username is optional.
func parseSubidFile(path string, uid int, username string) ([]SubIDRange, error) {
	uidS := strconv.Itoa(uid)
	var rangeList []SubIDRange

	subidFile, err := os.Open(path)
	if err != nil {
		return rangeList, err
	}
	defer subidFile.Close()

	s := bufio.NewScanner(subidFile)
	for s.Scan() {
		text := strings.TrimSpace(s.Text())
		if text == "" || strings.HasPrefix(text, "#") {
			continue
		}
		parts := strings.Split(text, ":")
		if len(parts) != 3 {
			return rangeList, fmt.Errorf("Cannot parse subuid/gid information: Format not correct for %s file", path)
		}
		if parts[0] == uidS || (username != "" && parts[0] == username) {
			startid, err := strconv.Atoi(parts[1])
			if err != nil {
				return rangeList, fmt.Errorf("String to int conversion failed during subuid/gid parsing of %s: %v", path, err)
			}
			length, err := strconv.Atoi(parts[2])
			if err != nil {
				return rangeList, fmt.Errorf("String to int conversion failed during subuid/gid parsing of %s: %v", path, err)
			}
			rangeList = append(rangeList, SubIDRange{startid, length})
		}
	}
	return rangeList, s.Err()
}