//go:build linux
// +build linux

package process

import (
	
	
	
	
	
	
	
	
	
	

	
	

	
	
	
)

var pageSize = uint64(os.Getpagesize())

const prioProcess = 0 // linux/resource.h

var clockTicks = 100 // default value

func init() {
	,  := sysconf.Sysconf(sysconf.SC_CLK_TCK)
	// ignore errors
	if  == nil {
		clockTicks = int()
	}
}

// MemoryInfoExStat is different between OSes
type MemoryInfoExStat struct {
	RSS    uint64 `json:"rss"`    // bytes
	VMS    uint64 `json:"vms"`    // bytes
	Shared uint64 `json:"shared"` // bytes
	Text   uint64 `json:"text"`   // bytes
	Lib    uint64 `json:"lib"`    // bytes
	Data   uint64 `json:"data"`   // bytes
	Dirty  uint64 `json:"dirty"`  // bytes
}

func ( MemoryInfoExStat) () string {
	,  := json.Marshal()
	return string()
}

type MemoryMapsStat struct {
	Path         string `json:"path"`
	Rss          uint64 `json:"rss"`
	Size         uint64 `json:"size"`
	Pss          uint64 `json:"pss"`
	SharedClean  uint64 `json:"sharedClean"`
	SharedDirty  uint64 `json:"sharedDirty"`
	PrivateClean uint64 `json:"privateClean"`
	PrivateDirty uint64 `json:"privateDirty"`
	Referenced   uint64 `json:"referenced"`
	Anonymous    uint64 `json:"anonymous"`
	Swap         uint64 `json:"swap"`
}

// String returns JSON value of the process.
func ( MemoryMapsStat) () string {
	,  := json.Marshal()
	return string()
}

func ( *Process) ( context.Context) (int32, error) {
	, , , , , , ,  := .fillFromStatWithContext()
	if  != nil {
		return -1, 
	}
	return , nil
}

func ( *Process) ( context.Context) (string, error) {
	if .name == "" {
		if  := .fillNameWithContext();  != nil {
			return "", 
		}
	}
	return .name, nil
}

func ( *Process) ( context.Context) (int32, error) {
	if .tgid == 0 {
		if  := .fillFromStatusWithContext();  != nil {
			return 0, 
		}
	}
	return .tgid, nil
}

func ( *Process) ( context.Context) (string, error) {
	return .fillFromExeWithContext()
}

func ( *Process) ( context.Context) (string, error) {
	return .fillFromCmdlineWithContext()
}

func ( *Process) ( context.Context) ([]string, error) {
	return .fillSliceFromCmdlineWithContext()
}

func ( *Process) ( context.Context) (int64, error) {
	, , , , , , ,  := .fillFromStatWithContext()
	if  != nil {
		return 0, 
	}
	return , nil
}

func ( *Process) ( context.Context) (string, error) {
	return .fillFromCwdWithContext()
}

func ( *Process) ( context.Context) ([]string, error) {
	 := .fillFromStatusWithContext()
	if  != nil {
		return []string{""}, 
	}
	return []string{.status}, nil
}

func ( *Process) ( context.Context) (bool, error) {
	// see https://github.com/shirou/gopsutil/issues/596#issuecomment-432707831 for implementation details
	 := .Pid
	 := common.HostProcWithContext(, strconv.Itoa(int()), "stat")
	,  := os.ReadFile()
	if  != nil {
		return false, 
	}
	 := strings.Fields(string())
	if len() < 8 {
		return false, fmt.Errorf("insufficient data in %s", )
	}
	 := [4]
	 := [7]
	return  == , nil
}

func ( *Process) ( context.Context) ([]int32, error) {
	 := .fillFromStatusWithContext()
	if  != nil {
		return []int32{}, 
	}
	return .uids, nil
}

func ( *Process) ( context.Context) ([]int32, error) {
	 := .fillFromStatusWithContext()
	if  != nil {
		return []int32{}, 
	}
	return .gids, nil
}

func ( *Process) ( context.Context) ([]int32, error) {
	 := .fillFromStatusWithContext()
	if  != nil {
		return []int32{}, 
	}
	return .groups, nil
}

func ( *Process) ( context.Context) (string, error) {
	, , , , , , ,  := .fillFromStatWithContext()
	if  != nil {
		return "", 
	}
	,  := getTerminalMap()
	if  != nil {
		return "", 
	}
	 := []
	return , nil
}

func ( *Process) ( context.Context) (int32, error) {
	, , , , , , ,  := .fillFromStatWithContext()
	if  != nil {
		return 0, 
	}
	return , nil
}

func ( *Process) ( context.Context) (int32, error) {
	return 0, common.ErrNotImplementedError
}

func ( *Process) ( context.Context) ([]RlimitStat, error) {
	return .RlimitUsageWithContext(, false)
}

func ( *Process) ( context.Context,  bool) ([]RlimitStat, error) {
	,  := .fillFromLimitsWithContext()
	if ! ||  != nil {
		return , 
	}

	, , , , , , ,  := .fillFromStatWithContext()
	if  != nil {
		return nil, 
	}
	if  := .fillFromStatusWithContext();  != nil {
		return nil, 
	}

	for  := range  {
		 := &[]
		switch .Resource {
		case RLIMIT_CPU:
			,  := .TimesWithContext()
			if  != nil {
				return nil, 
			}
			.Used = uint64(.User + .System)
		case RLIMIT_DATA:
			.Used = uint64(.memInfo.Data)
		case RLIMIT_STACK:
			.Used = uint64(.memInfo.Stack)
		case RLIMIT_RSS:
			.Used = uint64(.memInfo.RSS)
		case RLIMIT_NOFILE:
			,  := .NumFDsWithContext()
			if  != nil {
				return nil, 
			}
			.Used = uint64()
		case RLIMIT_MEMLOCK:
			.Used = uint64(.memInfo.Locked)
		case RLIMIT_AS:
			.Used = uint64(.memInfo.VMS)
		case RLIMIT_LOCKS:
			// TODO we can get the used value from /proc/$pid/locks. But linux doesn't enforce it, so not a high priority.
		case RLIMIT_SIGPENDING:
			.Used = .sigInfo.PendingProcess
		case RLIMIT_NICE:
			// The rlimit for nice is a little unusual, in that 0 means the niceness cannot be decreased beyond the current value, but it can be increased.
			// So effectively: if rs.Soft == 0 { rs.Soft = rs.Used }
			.Used = uint64()
		case RLIMIT_RTPRIO:
			.Used = uint64()
		}
	}

	return , 
}

func ( *Process) ( context.Context) (*IOCountersStat, error) {
	return .fillFromIOWithContext()
}

func ( *Process) ( context.Context) (*NumCtxSwitchesStat, error) {
	 := .fillFromStatusWithContext()
	if  != nil {
		return nil, 
	}
	return .numCtxSwitches, nil
}

func ( *Process) ( context.Context) (int32, error) {
	, ,  := .fillFromfdListWithContext()
	return int32(len()), 
}

func ( *Process) ( context.Context) (int32, error) {
	 := .fillFromStatusWithContext()
	if  != nil {
		return 0, 
	}
	return .numThreads, nil
}

func ( *Process) ( context.Context) (map[int32]*cpu.TimesStat, error) {
	 := make(map[int32]*cpu.TimesStat)
	 := common.HostProcWithContext(, strconv.Itoa(int(.Pid)), "task")

	,  := readPidsFromDir()
	if  != nil {
		return nil, 
	}

	for ,  := range  {
		, , , , , , ,  := .fillFromTIDStatWithContext(, )
		if  != nil {
			return nil, 
		}
		[] = 
	}

	return , nil
}

func ( *Process) ( context.Context) (*cpu.TimesStat, error) {
	, , , , , , ,  := .fillFromStatWithContext()
	if  != nil {
		return nil, 
	}
	return , nil
}

func ( *Process) ( context.Context) ([]int32, error) {
	return nil, common.ErrNotImplementedError
}

func ( *Process) ( context.Context) (*MemoryInfoStat, error) {
	, ,  := .fillFromStatmWithContext()
	if  != nil {
		return nil, 
	}
	return , nil
}

func ( *Process) ( context.Context) (*MemoryInfoExStat, error) {
	, ,  := .fillFromStatmWithContext()
	if  != nil {
		return nil, 
	}
	return , nil
}

func ( *Process) ( context.Context) (*PageFaultsStat, error) {
	, , , , , , ,  := .fillFromStatWithContext()
	if  != nil {
		return nil, 
	}
	return , nil
}

func ( *Process) ( context.Context) ([]*Process, error) {
	,  := common.CallPgrepWithContext(, invoke, .Pid)
	if  != nil {
		return nil, 
	}
	if len() == 0 {
		return nil, ErrorNoChildren
	}
	 := make([]*Process, 0, len())
	for ,  := range  {
		,  := NewProcessWithContext(, )
		if  != nil {
			return nil, 
		}
		 = append(, )
	}
	return , nil
}

func ( *Process) ( context.Context) ([]OpenFilesStat, error) {
	, ,  := .fillFromfdWithContext()
	if  != nil {
		return nil, 
	}
	 := make([]OpenFilesStat, len())
	for ,  := range  {
		[] = *
	}

	return , nil
}

func ( *Process) ( context.Context) ([]net.ConnectionStat, error) {
	return net.ConnectionsPidWithContext(, "all", .Pid)
}

func ( *Process) ( context.Context,  int) ([]net.ConnectionStat, error) {
	return net.ConnectionsPidMaxWithContext(, "all", .Pid, )
}

func ( *Process) ( context.Context,  bool) (*[]MemoryMapsStat, error) {
	 := .Pid
	var  []MemoryMapsStat
	 := common.HostProcWithContext(, strconv.Itoa(int()), "smaps")
	if  {
		 = make([]MemoryMapsStat, 1)
		// If smaps_rollup exists (require kernel >= 4.15), then we will use it
		// for pre-summed memory information for a process.
		 := common.HostProcWithContext(, strconv.Itoa(int()), "smaps_rollup")
		if ,  := os.Stat(); !os.IsNotExist() {
			 = 
		}
	}
	,  := os.ReadFile()
	if  != nil {
		return nil, 
	}
	 := strings.Split(string(), "\n")

	// function of parsing a block
	 := func( []string,  []string) (MemoryMapsStat, error) {
		 := MemoryMapsStat{}
		.Path = [len()-1]

		for ,  := range  {
			if strings.Contains(, "VmFlags") {
				continue
			}
			 := strings.Split(, ":")
			if len() < 2 {
				continue
			}
			 := strings.Trim([1], "kB") // remove last "kB"
			 = strings.TrimSpace()
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return , 
			}

			switch [0] {
			case "Size":
				.Size = 
			case "Rss":
				.Rss = 
			case "Pss":
				.Pss = 
			case "Shared_Clean":
				.SharedClean = 
			case "Shared_Dirty":
				.SharedDirty = 
			case "Private_Clean":
				.PrivateClean = 
			case "Private_Dirty":
				.PrivateDirty = 
			case "Referenced":
				.Referenced = 
			case "Anonymous":
				.Anonymous = 
			case "Swap":
				.Swap = 
			}
		}
		return , nil
	}

	var  []string
	 := make([]string, 0, 16)

	for ,  := range  {
		 := strings.Fields()
		if (len() > 0 && !strings.HasSuffix([0], ":")) ||  == len()-1 {
			// new block section
			if len() > 0 && len() > 0 {
				,  := (, )
				if  != nil {
					return &, 
				}
				if  {
					[0].Size += .Size
					[0].Rss += .Rss
					[0].Pss += .Pss
					[0].SharedClean += .SharedClean
					[0].SharedDirty += .SharedDirty
					[0].PrivateClean += .PrivateClean
					[0].PrivateDirty += .PrivateDirty
					[0].Referenced += .Referenced
					[0].Anonymous += .Anonymous
					[0].Swap += .Swap
				} else {
					 = append(, )
				}
			}
			// starts new block
			 = make([]string, 0, 16)
			 = 
		} else {
			 = append(, )
		}
	}

	return &, nil
}

func ( *Process) ( context.Context) ([]string, error) {
	 := common.HostProcWithContext(, strconv.Itoa(int(.Pid)), "environ")

	,  := os.ReadFile()
	if  != nil {
		return nil, 
	}

	return strings.Split(string(), "\000"), nil
}

/**
** Internal functions
**/

func limitToUint( string) (uint64, error) {
	if  == "unlimited" {
		return math.MaxUint64, nil
	}
	,  := strconv.ParseUint(, 10, 64)
	if  != nil {
		return 0, 
	}
	return , nil
}

// Get num_fds from /proc/(pid)/limits
func ( *Process) ( context.Context) ([]RlimitStat, error) {
	 := .Pid
	 := common.HostProcWithContext(, strconv.Itoa(int()), "limits")
	,  := os.Open()
	if  != nil {
		return nil, 
	}
	defer .Close()

	var  []RlimitStat

	 := bufio.NewScanner()
	for .Scan() {
		var  RlimitStat

		 := strings.Fields(.Text())

		// Remove the header line
		if strings.Contains([len()-1], "Units") {
			continue
		}

		// Assert that last item is a Hard limit
		.Hard,  = limitToUint([len()-1])
		if  != nil {
			// On error remove last item and try once again since it can be unit or header line
			 = [:len()-1]
			.Hard,  = limitToUint([len()-1])
			if  != nil {
				return nil, 
			}
		}
		// Remove last item from string
		 = [:len()-1]

		// Now last item is a Soft limit
		.Soft,  = limitToUint([len()-1])
		if  != nil {
			return nil, 
		}
		// Remove last item from string
		 = [:len()-1]

		// The rest is a stats name
		 := strings.Join(, " ")
		switch  {
		case "Max cpu time":
			.Resource = RLIMIT_CPU
		case "Max file size":
			.Resource = RLIMIT_FSIZE
		case "Max data size":
			.Resource = RLIMIT_DATA
		case "Max stack size":
			.Resource = RLIMIT_STACK
		case "Max core file size":
			.Resource = RLIMIT_CORE
		case "Max resident set":
			.Resource = RLIMIT_RSS
		case "Max processes":
			.Resource = RLIMIT_NPROC
		case "Max open files":
			.Resource = RLIMIT_NOFILE
		case "Max locked memory":
			.Resource = RLIMIT_MEMLOCK
		case "Max address space":
			.Resource = RLIMIT_AS
		case "Max file locks":
			.Resource = RLIMIT_LOCKS
		case "Max pending signals":
			.Resource = RLIMIT_SIGPENDING
		case "Max msgqueue size":
			.Resource = RLIMIT_MSGQUEUE
		case "Max nice priority":
			.Resource = RLIMIT_NICE
		case "Max realtime priority":
			.Resource = RLIMIT_RTPRIO
		case "Max realtime timeout":
			.Resource = RLIMIT_RTTIME
		default:
			continue
		}

		 = append(, )
	}

	if  := .Err();  != nil {
		return nil, 
	}

	return , nil
}

// Get list of /proc/(pid)/fd files
func ( *Process) ( context.Context) (string, []string, error) {
	 := .Pid
	 := common.HostProcWithContext(, strconv.Itoa(int()), "fd")
	,  := os.Open()
	if  != nil {
		return , []string{}, 
	}
	defer .Close()
	,  := .Readdirnames(-1)
	return , , 
}

// Get num_fds from /proc/(pid)/fd
func ( *Process) ( context.Context) (int32, []*OpenFilesStat, error) {
	, ,  := .fillFromfdListWithContext()
	if  != nil {
		return 0, nil, 
	}
	 := int32(len())

	var  []*OpenFilesStat
	for ,  := range  {
		 := filepath.Join(, )
		,  := os.Readlink()
		if  != nil {
			continue
		}
		,  := strconv.ParseUint(, 10, 64)
		if  != nil {
			return , , 
		}
		 := &OpenFilesStat{
			Path: ,
			Fd:   ,
		}
		 = append(, )
	}

	return , , nil
}

// Get cwd from /proc/(pid)/cwd
func ( *Process) ( context.Context) (string, error) {
	 := .Pid
	 := common.HostProcWithContext(, strconv.Itoa(int()), "cwd")
	,  := os.Readlink()
	if  != nil {
		return "", 
	}
	return string(), nil
}

// Get exe from /proc/(pid)/exe
func ( *Process) ( context.Context) (string, error) {
	 := .Pid
	 := common.HostProcWithContext(, strconv.Itoa(int()), "exe")
	,  := os.Readlink()
	if  != nil {
		return "", 
	}
	return string(), nil
}

// Get cmdline from /proc/(pid)/cmdline
func ( *Process) ( context.Context) (string, error) {
	 := .Pid
	 := common.HostProcWithContext(, strconv.Itoa(int()), "cmdline")
	,  := os.ReadFile()
	if  != nil {
		return "", 
	}
	 := strings.FieldsFunc(string(), func( rune) bool {
		return  == '\u0000'
	})

	return strings.Join(, " "), nil
}

func ( *Process) ( context.Context) ([]string, error) {
	 := .Pid
	 := common.HostProcWithContext(, strconv.Itoa(int()), "cmdline")
	,  := os.ReadFile()
	if  != nil {
		return nil, 
	}
	if len() == 0 {
		return nil, nil
	}

	 = bytes.TrimRight(, "\x00")

	 := bytes.Split(, []byte{0})
	var  []string
	for ,  := range  {
		 = append(, string())
	}

	return , nil
}

// Get IO status from /proc/(pid)/io
func ( *Process) ( context.Context) (*IOCountersStat, error) {
	 := .Pid
	 := common.HostProcWithContext(, strconv.Itoa(int()), "io")
	,  := os.ReadFile()
	if  != nil {
		return nil, 
	}
	 := strings.Split(string(), "\n")
	 := &IOCountersStat{}

	for ,  := range  {
		 := strings.Fields()
		if len() < 2 {
			continue
		}
		,  := strconv.ParseUint([1], 10, 64)
		if  != nil {
			return nil, 
		}
		 := strings.TrimSuffix([0], ":")
		switch  {
		case "syscr":
			.ReadCount = 
		case "syscw":
			.WriteCount = 
		case "read_bytes":
			.ReadBytes = 
		case "write_bytes":
			.WriteBytes = 
		}
	}

	return , nil
}

// Get memory info from /proc/(pid)/statm
func ( *Process) ( context.Context) (*MemoryInfoStat, *MemoryInfoExStat, error) {
	 := .Pid
	 := common.HostProcWithContext(, strconv.Itoa(int()), "statm")
	,  := os.ReadFile()
	if  != nil {
		return nil, nil, 
	}
	 := strings.Split(string(), " ")

	,  := strconv.ParseUint([0], 10, 64)
	if  != nil {
		return nil, nil, 
	}
	,  := strconv.ParseUint([1], 10, 64)
	if  != nil {
		return nil, nil, 
	}
	 := &MemoryInfoStat{
		RSS:  * pageSize,
		VMS:  * pageSize,
	}

	,  := strconv.ParseUint([2], 10, 64)
	if  != nil {
		return nil, nil, 
	}
	,  := strconv.ParseUint([3], 10, 64)
	if  != nil {
		return nil, nil, 
	}
	,  := strconv.ParseUint([4], 10, 64)
	if  != nil {
		return nil, nil, 
	}
	,  := strconv.ParseUint([5], 10, 64)
	if  != nil {
		return nil, nil, 
	}

	 := &MemoryInfoExStat{
		RSS:     * pageSize,
		VMS:     * pageSize,
		Shared:  * pageSize,
		Text:    * pageSize,
		Lib:     * pageSize,
		Dirty:   * pageSize,
	}

	return , , nil
}

// Get name from /proc/(pid)/comm or /proc/(pid)/status
func ( *Process) ( context.Context) error {
	 := .fillFromCommWithContext()
	if  == nil && .name != "" && len(.name) < 15 {
		return nil
	}
	return .fillFromStatusWithContext()
}

// Get name from /proc/(pid)/comm
func ( *Process) ( context.Context) error {
	 := .Pid
	 := common.HostProcWithContext(, strconv.Itoa(int()), "comm")
	,  := os.ReadFile()
	if  != nil {
		return 
	}

	.name = strings.TrimSuffix(string(), "\n")
	return nil
}

// Get various status from /proc/(pid)/status
func ( *Process) () error {
	return .fillFromStatusWithContext(context.Background())
}

func ( *Process) ( context.Context) error {
	 := .Pid
	 := common.HostProcWithContext(, strconv.Itoa(int()), "status")
	,  := os.ReadFile()
	if  != nil {
		return 
	}
	 := strings.Split(string(), "\n")
	.numCtxSwitches = &NumCtxSwitchesStat{}
	.memInfo = &MemoryInfoStat{}
	.sigInfo = &SignalInfoStat{}
	for ,  := range  {
		 := strings.SplitN(, "\t", 2)
		if len() < 2 {
			continue
		}
		 := [1]
		switch strings.TrimRight([0], ":") {
		case "Name":
			.name = strings.Trim(, " \t")
			if len(.name) >= 15 {
				,  := .CmdlineSliceWithContext()
				if  != nil {
					return 
				}
				if len() > 0 {
					 := filepath.Base([0])
					if strings.HasPrefix(, .name) {
						.name = 
					}
				}
			}
			// Ensure we have a copy and not reference into slice
			.name = string([]byte(.name))
		case "State":
			.status = convertStatusChar([0:1])
			// Ensure we have a copy and not reference into slice
			.status = string([]byte(.status))
		case "PPid", "Ppid":
			,  := strconv.ParseInt(, 10, 32)
			if  != nil {
				return 
			}
			.parent = int32()
		case "Tgid":
			,  := strconv.ParseInt(, 10, 32)
			if  != nil {
				return 
			}
			.tgid = int32()
		case "Uid":
			.uids = make([]int32, 0, 4)
			for ,  := range strings.Split(, "\t") {
				,  := strconv.ParseInt(, 10, 32)
				if  != nil {
					return 
				}
				.uids = append(.uids, int32())
			}
		case "Gid":
			.gids = make([]int32, 0, 4)
			for ,  := range strings.Split(, "\t") {
				,  := strconv.ParseInt(, 10, 32)
				if  != nil {
					return 
				}
				.gids = append(.gids, int32())
			}
		case "Groups":
			 := strings.Fields()
			.groups = make([]int32, 0, len())
			for ,  := range  {
				,  := strconv.ParseInt(, 10, 32)
				if  != nil {
					return 
				}
				.groups = append(.groups, int32())
			}
		case "Threads":
			,  := strconv.ParseInt(, 10, 32)
			if  != nil {
				return 
			}
			.numThreads = int32()
		case "voluntary_ctxt_switches":
			,  := strconv.ParseInt(, 10, 64)
			if  != nil {
				return 
			}
			.numCtxSwitches.Voluntary = 
		case "nonvoluntary_ctxt_switches":
			,  := strconv.ParseInt(, 10, 64)
			if  != nil {
				return 
			}
			.numCtxSwitches.Involuntary = 
		case "VmRSS":
			 := strings.Trim(, " kB") // remove last "kB"
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return 
			}
			.memInfo.RSS =  * 1024
		case "VmSize":
			 := strings.Trim(, " kB") // remove last "kB"
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return 
			}
			.memInfo.VMS =  * 1024
		case "VmSwap":
			 := strings.Trim(, " kB") // remove last "kB"
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return 
			}
			.memInfo.Swap =  * 1024
		case "VmHWM":
			 := strings.Trim(, " kB") // remove last "kB"
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return 
			}
			.memInfo.HWM =  * 1024
		case "VmData":
			 := strings.Trim(, " kB") // remove last "kB"
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return 
			}
			.memInfo.Data =  * 1024
		case "VmStk":
			 := strings.Trim(, " kB") // remove last "kB"
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return 
			}
			.memInfo.Stack =  * 1024
		case "VmLck":
			 := strings.Trim(, " kB") // remove last "kB"
			,  := strconv.ParseUint(, 10, 64)
			if  != nil {
				return 
			}
			.memInfo.Locked =  * 1024
		case "SigPnd":
			if len() > 16 {
				 = [len()-16:]
			}
			,  := strconv.ParseUint(, 16, 64)
			if  != nil {
				return 
			}
			.sigInfo.PendingThread = 
		case "ShdPnd":
			if len() > 16 {
				 = [len()-16:]
			}
			,  := strconv.ParseUint(, 16, 64)
			if  != nil {
				return 
			}
			.sigInfo.PendingProcess = 
		case "SigBlk":
			if len() > 16 {
				 = [len()-16:]
			}
			,  := strconv.ParseUint(, 16, 64)
			if  != nil {
				return 
			}
			.sigInfo.Blocked = 
		case "SigIgn":
			if len() > 16 {
				 = [len()-16:]
			}
			,  := strconv.ParseUint(, 16, 64)
			if  != nil {
				return 
			}
			.sigInfo.Ignored = 
		case "SigCgt":
			if len() > 16 {
				 = [len()-16:]
			}
			,  := strconv.ParseUint(, 16, 64)
			if  != nil {
				return 
			}
			.sigInfo.Caught = 
		}

	}
	return nil
}

func ( *Process) ( int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
	return .fillFromTIDStatWithContext(context.Background(), )
}

func ( *Process) ( context.Context,  int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
	 := .Pid
	var  string

	if  == -1 {
		 = common.HostProcWithContext(, strconv.Itoa(int()), "stat")
	} else {
		 = common.HostProcWithContext(, strconv.Itoa(int()), "task", strconv.Itoa(int()), "stat")
	}

	,  := os.ReadFile()
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}
	// Indexing from one, as described in `man proc` about the file /proc/[pid]/stat
	 := splitProcStat()

	,  := strconv.ParseUint([7], 10, 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}

	,  := strconv.ParseInt([4], 10, 32)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}
	,  := strconv.ParseFloat([14], 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}

	,  := strconv.ParseFloat([15], 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}

	// There is no such thing as iotime in stat file.  As an approximation, we
	// will use delayacct_blkio_ticks (aggregated block I/O delays, as per Linux
	// docs).  Note: I am assuming at least Linux 2.6.18
	var  float64
	if len() > 42 {
		,  = strconv.ParseFloat([42], 64)
		if  != nil {
			 = 0 // Ancient linux version, most likely
		}
	} else {
		 = 0 // e.g. SmartOS containers
	}

	 := &cpu.TimesStat{
		CPU:    "cpu",
		User:    / float64(clockTicks),
		System:  / float64(clockTicks),
		Iowait:  / float64(clockTicks),
	}

	,  := common.BootTimeWithContext(, enableBootTimeCache)
	,  := strconv.ParseUint([22], 10, 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}
	 := ( / uint64(clockTicks)) + uint64()
	 := int64( * 1000)

	,  := strconv.ParseInt([18], 10, 32)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}
	if  < 0 {
		 = *-1 - 1
	} else {
		 = 0
	}

	//	p.Nice = mustParseInt32(fields[18])
	// use syscall instead of parse Stat file
	,  := unix.Getpriority(prioProcess, int())
	 := int32() // FIXME: is this true?

	,  := strconv.ParseUint([10], 10, 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}
	,  := strconv.ParseUint([11], 10, 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}
	,  := strconv.ParseUint([12], 10, 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}
	,  := strconv.ParseUint([13], 10, 64)
	if  != nil {
		return 0, 0, nil, 0, 0, 0, nil, 
	}

	 := &PageFaultsStat{
		MinorFaults:      ,
		MajorFaults:      ,
		ChildMinorFaults: ,
		ChildMajorFaults: ,
	}

	return , int32(), , , uint32(), , , nil
}

func ( *Process) ( context.Context) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
	return .fillFromTIDStatWithContext(, -1)
}

func pidsWithContext( context.Context) ([]int32, error) {
	return readPidsFromDir(common.HostProcWithContext())
}

func ( context.Context) ([]*Process, error) {
	 := []*Process{}

	,  := PidsWithContext()
	if  != nil {
		return , 
	}

	for ,  := range  {
		,  := NewProcessWithContext(, )
		if  != nil {
			continue
		}
		 = append(, )
	}

	return , nil
}

func readPidsFromDir( string) ([]int32, error) {
	var  []int32

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

	,  := .Readdirnames(-1)
	if  != nil {
		return nil, 
	}
	for ,  := range  {
		,  := strconv.ParseInt(, 10, 32)
		if  != nil {
			// if not numeric name, just skip
			continue
		}
		 = append(, int32())
	}

	return , nil
}

func splitProcStat( []byte) []string {
	 := bytes.IndexByte(, '(')
	 := bytes.LastIndexByte(, ')')
	 := strings.Fields(string([+2:])) // +2 skip ') '
	 := [+1 : ]
	 := strings.TrimSpace(string([:]))
	 := make([]string, 3, len()+3)
	[1] = string()
	[2] = string()
	 = append(, ...)
	return 
}