github.com/rootless-containers/rootlesskit/v2@v2.3.4/pkg/parent/idtools/idtools.go (about) 1 // Package idtools is forked from https://github.com/moby/moby/tree/298ba5b13150bfffe8414922a951a7a793276d31/pkg/idtools 2 package idtools 3 4 import ( 5 "bufio" 6 "fmt" 7 "os" 8 "strconv" 9 "strings" 10 ) 11 12 type SubIDRange struct { 13 Start int 14 Length int 15 } 16 17 const ( 18 subuidFileName = "/etc/subuid" 19 subgidFileName = "/etc/subgid" 20 ) 21 22 func GetSubIDRanges(uid int, username string) ([]SubIDRange, []SubIDRange, error) { 23 subuidRanges, err := parseSubuid(uid, username) 24 if err != nil { 25 return nil, nil, err 26 } 27 subgidRanges, err := parseSubgid(uid, username) 28 if err != nil { 29 return nil, nil, err 30 } 31 if len(subuidRanges) == 0 { 32 return nil, nil, fmt.Errorf("No subuid ranges found for user %d (%q)", uid, username) 33 } 34 if len(subgidRanges) == 0 { 35 return nil, nil, fmt.Errorf("No subgid ranges found for user %d (%q)", uid, username) 36 } 37 return subuidRanges, subgidRanges, nil 38 } 39 40 func parseSubuid(uid int, username string) ([]SubIDRange, error) { 41 return parseSubidFile(subuidFileName, uid, username) 42 } 43 44 func parseSubgid(uid int, username string) ([]SubIDRange, error) { 45 return parseSubidFile(subgidFileName, uid, username) 46 } 47 48 // parseSubidFile will read the appropriate file (/etc/subuid or /etc/subgid) 49 // and return all found ranges for a specified user. username is optional. 50 func parseSubidFile(path string, uid int, username string) ([]SubIDRange, error) { 51 uidS := strconv.Itoa(uid) 52 var rangeList []SubIDRange 53 54 subidFile, err := os.Open(path) 55 if err != nil { 56 return rangeList, err 57 } 58 defer subidFile.Close() 59 60 s := bufio.NewScanner(subidFile) 61 for s.Scan() { 62 text := strings.TrimSpace(s.Text()) 63 if text == "" || strings.HasPrefix(text, "#") { 64 continue 65 } 66 parts := strings.Split(text, ":") 67 if len(parts) != 3 { 68 return rangeList, fmt.Errorf("Cannot parse subuid/gid information: Format not correct for %s file", path) 69 } 70 if parts[0] == uidS || (username != "" && parts[0] == username) { 71 startid, err := strconv.Atoi(parts[1]) 72 if err != nil { 73 return rangeList, fmt.Errorf("String to int conversion failed during subuid/gid parsing of %s: %v", path, err) 74 } 75 length, err := strconv.Atoi(parts[2]) 76 if err != nil { 77 return rangeList, fmt.Errorf("String to int conversion failed during subuid/gid parsing of %s: %v", path, err) 78 } 79 rangeList = append(rangeList, SubIDRange{startid, length}) 80 } 81 } 82 return rangeList, s.Err() 83 }