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()
}
|