gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

utils.go (3483B)


      1 /*
      2    Copyright The containerd Authors.
      3 
      4    Licensed under the Apache License, Version 2.0 (the "License");
      5    you may not use this file except in compliance with the License.
      6    You may obtain a copy of the License at
      7 
      8        http://www.apache.org/licenses/LICENSE-2.0
      9 
     10    Unless required by applicable law or agreed to in writing, software
     11    distributed under the License is distributed on an "AS IS" BASIS,
     12    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13    See the License for the specific language governing permissions and
     14    limitations under the License.
     15 */
     16 
     17 package cgroups
     18 
     19 import (
     20 	"bufio"
     21 	"fmt"
     22 	"io"
     23 	"os"
     24 	"path/filepath"
     25 	"strings"
     26 	"sync"
     27 
     28 	"golang.org/x/sys/unix"
     29 )
     30 
     31 var (
     32 	nsOnce    sync.Once
     33 	inUserNS  bool
     34 	checkMode sync.Once
     35 	cgMode    CGMode
     36 )
     37 
     38 const unifiedMountpoint = "/sys/fs/cgroup"
     39 
     40 // CGMode is the cgroups mode of the host system
     41 type CGMode int
     42 
     43 const (
     44 	// Unavailable cgroup mountpoint
     45 	Unavailable CGMode = iota
     46 	// Legacy cgroups v1
     47 	Legacy
     48 	// Hybrid with cgroups v1 and v2 controllers mounted
     49 	Hybrid
     50 	// Unified with only cgroups v2 mounted
     51 	Unified
     52 )
     53 
     54 // Mode returns the cgroups mode running on the host
     55 func Mode() CGMode {
     56 	checkMode.Do(func() {
     57 		var st unix.Statfs_t
     58 		if err := unix.Statfs(unifiedMountpoint, &st); err != nil {
     59 			cgMode = Unavailable
     60 			return
     61 		}
     62 		switch st.Type {
     63 		case unix.CGROUP2_SUPER_MAGIC:
     64 			cgMode = Unified
     65 		default:
     66 			cgMode = Legacy
     67 			if err := unix.Statfs(filepath.Join(unifiedMountpoint, "unified"), &st); err != nil {
     68 				return
     69 			}
     70 			if st.Type == unix.CGROUP2_SUPER_MAGIC {
     71 				cgMode = Hybrid
     72 			}
     73 		}
     74 	})
     75 	return cgMode
     76 }
     77 
     78 // RunningInUserNS detects whether we are currently running in a user namespace.
     79 // Copied from github.com/lxc/lxd/shared/util.go
     80 func RunningInUserNS() bool {
     81 	nsOnce.Do(func() {
     82 		file, err := os.Open("/proc/self/uid_map")
     83 		if err != nil {
     84 			// This kernel-provided file only exists if user namespaces are supported
     85 			return
     86 		}
     87 		defer file.Close()
     88 
     89 		buf := bufio.NewReader(file)
     90 		l, _, err := buf.ReadLine()
     91 		if err != nil {
     92 			return
     93 		}
     94 
     95 		line := string(l)
     96 		var a, b, c int64
     97 		fmt.Sscanf(line, "%d %d %d", &a, &b, &c)
     98 
     99 		/*
    100 		 * We assume we are in the initial user namespace if we have a full
    101 		 * range - 4294967295 uids starting at uid 0.
    102 		 */
    103 		if a == 0 && b == 0 && c == 4294967295 {
    104 			return
    105 		}
    106 		inUserNS = true
    107 	})
    108 	return inUserNS
    109 }
    110 
    111 // ParseCgroupFileUnified returns legacy subsystem paths as the first value,
    112 // and returns the unified path as the second value.
    113 func ParseCgroupFileUnified(path string) (map[string]string, string, error) {
    114 	f, err := os.Open(path)
    115 	if err != nil {
    116 		return nil, "", err
    117 	}
    118 	defer f.Close()
    119 	return ParseCgroupFromReaderUnified(f)
    120 }
    121 
    122 // ParseCgroupFromReaderUnified returns legacy subsystem paths as the first value,
    123 // and returns the unified path as the second value.
    124 func ParseCgroupFromReaderUnified(r io.Reader) (map[string]string, string, error) {
    125 	var (
    126 		cgroups = make(map[string]string)
    127 		unified = ""
    128 		s       = bufio.NewScanner(r)
    129 	)
    130 	for s.Scan() {
    131 		var (
    132 			text  = s.Text()
    133 			parts = strings.SplitN(text, ":", 3)
    134 		)
    135 		if len(parts) < 3 {
    136 			return nil, unified, fmt.Errorf("invalid cgroup entry: %q", text)
    137 		}
    138 		for _, subs := range strings.Split(parts[1], ",") {
    139 			if subs == "" {
    140 				unified = parts[2]
    141 			} else {
    142 				cgroups[subs] = parts[2]
    143 			}
    144 		}
    145 	}
    146 	if err := s.Err(); err != nil {
    147 		return nil, unified, err
    148 	}
    149 	return cgroups, unified, nil
    150 }