 9bdcbe0447
			
		
	
	9bdcbe0447
	
	
	
		
			
			Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			565 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			565 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // +build aix
 | |
| 
 | |
| package gosigar
 | |
| 
 | |
| /*
 | |
| #cgo LDFLAGS: -L/usr/lib -lperfstat
 | |
| 
 | |
| #include <libperfstat.h>
 | |
| #include <procinfo.h>
 | |
| #include <unistd.h>
 | |
| #include <utmp.h>
 | |
| #include <sys/mntctl.h>
 | |
| #include <sys/proc.h>
 | |
| #include <sys/types.h>
 | |
| #include <sys/vmount.h>
 | |
| 
 | |
| */
 | |
| import "C"
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"encoding/binary"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"os"
 | |
| 	"os/user"
 | |
| 	"runtime"
 | |
| 	"strconv"
 | |
| 	"syscall"
 | |
| 	"time"
 | |
| 	"unsafe"
 | |
| )
 | |
| 
 | |
| var system struct {
 | |
| 	ticks    uint64
 | |
| 	btime    uint64
 | |
| 	pagesize uint64
 | |
| }
 | |
| 
 | |
| func init() {
 | |
| 	// sysconf(_SC_CLK_TCK) returns the number of ticks by second.
 | |
| 	system.ticks = uint64(C.sysconf(C._SC_CLK_TCK))
 | |
| 	system.pagesize = uint64(os.Getpagesize())
 | |
| }
 | |
| 
 | |
| // utmp can't be used by "encoding/binary" if generated by cgo,
 | |
| // some pads will be explicitly missing.
 | |
| type utmp struct {
 | |
| 	User        [256]uint8
 | |
| 	ID          [14]uint8
 | |
| 	Line        [64]uint8
 | |
| 	XPad1       int16
 | |
| 	Pid         int32
 | |
| 	Type        int16
 | |
| 	XPad2       int16
 | |
| 	Time        int64
 | |
| 	Termination int16
 | |
| 	Exit        int16
 | |
| 	Host        [256]uint8
 | |
| 	XdblWordPad int32
 | |
| 	XreservedA  [2]int32
 | |
| 	XreservedV  [6]int32
 | |
| }
 | |
| 
 | |
| func bootTime() (uint64, error) {
 | |
| 	if system.btime != 0 {
 | |
| 		return system.btime, nil
 | |
| 	}
 | |
| 
 | |
| 	// Get boot time from /etc/utmp
 | |
| 	file, err := os.Open("/etc/utmp")
 | |
| 	if err != nil {
 | |
| 		return 0, fmt.Errorf("error while opening /etc/utmp: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	defer file.Close()
 | |
| 
 | |
| 	for {
 | |
| 		var utmp utmp
 | |
| 		if err := binary.Read(file, binary.BigEndian, &utmp); err != nil {
 | |
| 			break
 | |
| 		}
 | |
| 
 | |
| 		if utmp.Type == C.BOOT_TIME {
 | |
| 			system.btime = uint64(utmp.Time)
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 	return system.btime, nil
 | |
| }
 | |
| 
 | |
| func tick2msec(val uint64) uint64 {
 | |
| 	return val * 1000 / system.ticks
 | |
| }
 | |
| 
 | |
| // Get returns the list of file systems
 | |
| func (self *FileSystemList) Get() error {
 | |
| 	var size C.int
 | |
| 	_, err := C.mntctl(C.MCTL_QUERY, C.sizeof_int, (*C.char)(unsafe.Pointer(&size)))
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("error while retrieving file system number: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	buf := make([]byte, size)
 | |
| 	num, err := C.mntctl(C.MCTL_QUERY, C.ulong(size), (*C.char)(&buf[0]))
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("error while retrieving file system list: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	// Vmount structure has a fixed size area for common data (type,
 | |
| 	// offsets, etc) and another area with variable length data (devname,
 | |
| 	// options, etc). These data can be accessed based on the offsets
 | |
| 	// stored in an array inside the fixed part. They can be retrieve
 | |
| 	// using index given by C define.
 | |
| 	vmt2data := func(buf []byte, ent *C.struct_vmount, idx int, baseOff int) []byte {
 | |
| 		off := int(ent.vmt_data[idx].vmt_off)
 | |
| 		size := int(ent.vmt_data[idx].vmt_size)
 | |
| 		return buf[baseOff+off : baseOff+off+size]
 | |
| 	}
 | |
| 
 | |
| 	entOff := 0
 | |
| 
 | |
| 	fslist := make([]FileSystem, num)
 | |
| 	for i := 0; i < int(num); i++ {
 | |
| 		ent := (*C.struct_vmount)(unsafe.Pointer(&buf[entOff]))
 | |
| 		fs := &fslist[i]
 | |
| 
 | |
| 		// Correspondances taken for /etc/vfs
 | |
| 		switch ent.vmt_gfstype {
 | |
| 		case C.MNT_AIX:
 | |
| 			fs.SysTypeName = "jfs2"
 | |
| 		case C.MNT_NAMEFS:
 | |
| 			fs.SysTypeName = "namefs"
 | |
| 		case C.MNT_NFS:
 | |
| 			fs.SysTypeName = "nfs"
 | |
| 		case C.MNT_JFS:
 | |
| 			fs.SysTypeName = "jfs"
 | |
| 		case C.MNT_CDROM:
 | |
| 			fs.SysTypeName = "cdrom"
 | |
| 		case C.MNT_PROCFS:
 | |
| 			fs.SysTypeName = "proc"
 | |
| 		case C.MNT_SFS:
 | |
| 			fs.SysTypeName = "sfs"
 | |
| 		case C.MNT_CACHEFS:
 | |
| 			fs.SysTypeName = "cachefs"
 | |
| 		case C.MNT_NFS3:
 | |
| 			fs.SysTypeName = "nfs3"
 | |
| 		case C.MNT_AUTOFS:
 | |
| 			fs.SysTypeName = "autofs"
 | |
| 		case C.MNT_POOLFS:
 | |
| 			fs.SysTypeName = "poolfs"
 | |
| 		case C.MNT_UDF:
 | |
| 			fs.SysTypeName = "udfs"
 | |
| 		case C.MNT_NFS4:
 | |
| 			fs.SysTypeName = "nfs4"
 | |
| 		case C.MNT_CIFS:
 | |
| 			fs.SysTypeName = "cifs"
 | |
| 		case C.MNT_PMEMFS:
 | |
| 			fs.SysTypeName = "pmemfs"
 | |
| 		case C.MNT_AHAFS:
 | |
| 			fs.SysTypeName = "ahafs"
 | |
| 		case C.MNT_STNFS:
 | |
| 			fs.SysTypeName = "stnfs"
 | |
| 		default:
 | |
| 			if ent.vmt_flags&C.MNT_REMOTE != 0 {
 | |
| 				fs.SysTypeName = "network"
 | |
| 			} else {
 | |
| 				fs.SysTypeName = "none"
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		fs.DirName = convertBytesToString(vmt2data(buf, ent, C.VMT_STUB, entOff))
 | |
| 		fs.Options = convertBytesToString(vmt2data(buf, ent, C.VMT_ARGS, entOff))
 | |
| 		devname := convertBytesToString(vmt2data(buf, ent, C.VMT_OBJECT, entOff))
 | |
| 		if ent.vmt_flags&C.MNT_REMOTE != 0 {
 | |
| 			hostname := convertBytesToString(vmt2data(buf, ent, C.VMT_OBJECT, entOff))
 | |
| 			fs.DevName = hostname + ":" + devname
 | |
| 		} else {
 | |
| 			fs.DevName = devname
 | |
| 		}
 | |
| 
 | |
| 		entOff += int(ent.vmt_length)
 | |
| 	}
 | |
| 
 | |
| 	self.List = fslist
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Get returns the CPU load average
 | |
| func (self *LoadAverage) Get() error {
 | |
| 	cpudata := C.perfstat_cpu_total_t{}
 | |
| 
 | |
| 	if _, err := C.perfstat_cpu_total(nil, &cpudata, C.sizeof_perfstat_cpu_total_t, 1); err != nil {
 | |
| 		return fmt.Errorf("perfstat_cpu_total: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	// from libperfstat.h:
 | |
| 	// "To calculate the load average, divide the numbers by (1<<SBITS).
 | |
| 	//  SBITS is defined in <sys/proc.h>."
 | |
| 	fixedToFloat64 := func(x uint64) float64 {
 | |
| 		return float64(x) / (1 << C.SBITS)
 | |
| 	}
 | |
| 	self.One = fixedToFloat64(uint64(cpudata.loadavg[0]))
 | |
| 	self.Five = fixedToFloat64(uint64(cpudata.loadavg[1]))
 | |
| 	self.Fifteen = fixedToFloat64(uint64(cpudata.loadavg[2]))
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Get returns the system uptime
 | |
| func (self *Uptime) Get() error {
 | |
| 	btime, err := bootTime()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	uptime := time.Now().Sub(time.Unix(int64(btime), 0))
 | |
| 	self.Length = uptime.Seconds()
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Get returns the current system memory
 | |
| func (self *Mem) Get() error {
 | |
| 	meminfo := C.perfstat_memory_total_t{}
 | |
| 	_, err := C.perfstat_memory_total(nil, &meminfo, C.sizeof_perfstat_memory_total_t, 1)
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("perfstat_memory_total: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	self.Total = uint64(meminfo.real_total) * system.pagesize
 | |
| 	self.Free = uint64(meminfo.real_free) * system.pagesize
 | |
| 
 | |
| 	kern := uint64(meminfo.numperm) * system.pagesize // number of pages in file cache
 | |
| 
 | |
| 	self.Used = self.Total - self.Free
 | |
| 	self.ActualFree = self.Free + kern
 | |
| 	self.ActualUsed = self.Used - kern
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Get returns the current system swap memory
 | |
| func (self *Swap) Get() error {
 | |
| 	ps := C.perfstat_pagingspace_t{}
 | |
| 	id := C.perfstat_id_t{}
 | |
| 
 | |
| 	id.name[0] = 0
 | |
| 
 | |
| 	for {
 | |
| 		// errno can be set during perfstat_pagingspace's call even
 | |
| 		// if it succeeds. Thus, only check it when the result is -1.
 | |
| 		if r, err := C.perfstat_pagingspace(&id, &ps, C.sizeof_perfstat_pagingspace_t, 1); r == -1 && err != nil {
 | |
| 			return fmt.Errorf("perfstat_memory_total: %s", err)
 | |
| 		}
 | |
| 
 | |
| 		if ps.active != 1 {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		// convert MB sizes to bytes
 | |
| 		self.Total += uint64(ps.mb_size) * 1024 * 1024
 | |
| 		self.Used += uint64(ps.mb_used) * 1024 * 1024
 | |
| 
 | |
| 		if id.name[0] == 0 {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	self.Free = self.Total - self.Used
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Get returns information about a CPU
 | |
| func (self *Cpu) Get() error {
 | |
| 	cpudata := C.perfstat_cpu_total_t{}
 | |
| 
 | |
| 	if _, err := C.perfstat_cpu_total(nil, &cpudata, C.sizeof_perfstat_cpu_total_t, 1); err != nil {
 | |
| 		return fmt.Errorf("perfstat_cpu_total: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	self.User = tick2msec(uint64(cpudata.user))
 | |
| 	self.Sys = tick2msec(uint64(cpudata.sys))
 | |
| 	self.Idle = tick2msec(uint64(cpudata.idle))
 | |
| 	self.Wait = tick2msec(uint64(cpudata.wait))
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Get returns the list of CPU used by the system
 | |
| func (self *CpuList) Get() error {
 | |
| 	cpudata := C.perfstat_cpu_t{}
 | |
| 	id := C.perfstat_id_t{}
 | |
| 	id.name[0] = 0
 | |
| 
 | |
| 	// Retrieve the number of cpu using perfstat_cpu
 | |
| 	capacity, err := C.perfstat_cpu(nil, nil, C.sizeof_perfstat_cpu_t, 0)
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("error while retrieving CPU number: %s", err)
 | |
| 	}
 | |
| 	list := make([]Cpu, 0, capacity)
 | |
| 
 | |
| 	for {
 | |
| 		if _, err := C.perfstat_cpu(&id, &cpudata, C.sizeof_perfstat_cpu_t, 1); err != nil {
 | |
| 			return fmt.Errorf("perfstat_cpu: %s", err)
 | |
| 		}
 | |
| 
 | |
| 		cpu := Cpu{}
 | |
| 		cpu.User = tick2msec(uint64(cpudata.user))
 | |
| 		cpu.Sys = tick2msec(uint64(cpudata.sys))
 | |
| 		cpu.Idle = tick2msec(uint64(cpudata.idle))
 | |
| 		cpu.Wait = tick2msec(uint64(cpudata.wait))
 | |
| 
 | |
| 		list = append(list, cpu)
 | |
| 
 | |
| 		if id.name[0] == 0 {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	self.List = list
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Get returns the list of all active processes
 | |
| func (self *ProcList) Get() error {
 | |
| 	info := C.struct_procsinfo64{}
 | |
| 	pid := C.pid_t(0)
 | |
| 
 | |
| 	var list []int
 | |
| 
 | |
| 	for {
 | |
| 		// getprocs first argument is a void*
 | |
| 		num, err := C.getprocs(unsafe.Pointer(&info), C.sizeof_struct_procsinfo64, nil, 0, &pid, 1)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		list = append(list, int(info.pi_pid))
 | |
| 
 | |
| 		if num == 0 {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	self.List = list
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Get returns information about a process
 | |
| func (self *ProcState) Get(pid int) error {
 | |
| 	info := C.struct_procsinfo64{}
 | |
| 	cpid := C.pid_t(pid)
 | |
| 
 | |
| 	num, err := C.getprocs(unsafe.Pointer(&info), C.sizeof_struct_procsinfo64, nil, 0, &cpid, 1)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	if num != 1 {
 | |
| 		return syscall.ESRCH
 | |
| 	}
 | |
| 
 | |
| 	self.Name = C.GoString(&info.pi_comm[0])
 | |
| 	self.Ppid = int(info.pi_ppid)
 | |
| 	self.Pgid = int(info.pi_pgrp)
 | |
| 	self.Nice = int(info.pi_nice)
 | |
| 	self.Tty = int(info.pi_ttyd)
 | |
| 	self.Priority = int(info.pi_pri)
 | |
| 
 | |
| 	switch info.pi_state {
 | |
| 	case C.SACTIVE:
 | |
| 		self.State = RunStateRun
 | |
| 	case C.SIDL:
 | |
| 		self.State = RunStateIdle
 | |
| 	case C.SSTOP:
 | |
| 		self.State = RunStateStop
 | |
| 	case C.SZOMB:
 | |
| 		self.State = RunStateZombie
 | |
| 	case C.SSWAP:
 | |
| 		self.State = RunStateSleep
 | |
| 	default:
 | |
| 		self.State = RunStateUnknown
 | |
| 	}
 | |
| 
 | |
| 	// Get process username. Fallback to UID if username is not available.
 | |
| 	uid := strconv.Itoa(int(info.pi_uid))
 | |
| 	userID, err := user.LookupId(uid)
 | |
| 	if err == nil && userID.Username != "" {
 | |
| 		self.Username = userID.Username
 | |
| 	} else {
 | |
| 		self.Username = uid
 | |
| 	}
 | |
| 
 | |
| 	thrinfo := C.struct_thrdsinfo64{}
 | |
| 	tid := C.tid_t(0)
 | |
| 
 | |
| 	if _, err := C.getthrds(cpid, unsafe.Pointer(&thrinfo), C.sizeof_struct_thrdsinfo64, &tid, 1); err != nil {
 | |
| 		self.Processor = int(thrinfo.ti_affinity)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| //Get returns the current memory usage of a process
 | |
| func (self *ProcMem) Get(pid int) error {
 | |
| 	info := C.struct_procsinfo64{}
 | |
| 	cpid := C.pid_t(pid)
 | |
| 
 | |
| 	num, err := C.getprocs(unsafe.Pointer(&info), C.sizeof_struct_procsinfo64, nil, 0, &cpid, 1)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	if num != 1 {
 | |
| 		return syscall.ESRCH
 | |
| 	}
 | |
| 
 | |
| 	self.Size = uint64(info.pi_size) * system.pagesize
 | |
| 	self.Share = uint64(info.pi_sdsize) * system.pagesize
 | |
| 	self.Resident = uint64(info.pi_drss+info.pi_trss) * system.pagesize
 | |
| 
 | |
| 	self.MinorFaults = uint64(info.pi_minflt)
 | |
| 	self.MajorFaults = uint64(info.pi_majflt)
 | |
| 	self.PageFaults = self.MinorFaults + self.MajorFaults
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Get returns a process uptime
 | |
| func (self *ProcTime) Get(pid int) error {
 | |
| 	info := C.struct_procsinfo64{}
 | |
| 	cpid := C.pid_t(pid)
 | |
| 
 | |
| 	num, err := C.getprocs(unsafe.Pointer(&info), C.sizeof_struct_procsinfo64, nil, 0, &cpid, 1)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	if num != 1 {
 | |
| 		return syscall.ESRCH
 | |
| 	}
 | |
| 
 | |
| 	self.StartTime = uint64(info.pi_start) * 1000
 | |
| 	self.User = uint64(info.pi_utime) * 1000
 | |
| 	self.Sys = uint64(info.pi_stime) * 1000
 | |
| 	self.Total = self.User + self.Sys
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Get returns arguments of a process
 | |
| func (self *ProcArgs) Get(pid int) error {
 | |
| 	/* If buffer is not large enough, args are truncated */
 | |
| 	buf := make([]byte, 8192)
 | |
| 	info := C.struct_procsinfo64{}
 | |
| 	info.pi_pid = C.pid_t(pid)
 | |
| 
 | |
| 	if _, err := C.getargs(unsafe.Pointer(&info), C.sizeof_struct_procsinfo64, (*C.char)(&buf[0]), 8192); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	bbuf := bytes.NewBuffer(buf)
 | |
| 
 | |
| 	var args []string
 | |
| 
 | |
| 	for {
 | |
| 		arg, err := bbuf.ReadBytes(0)
 | |
| 		if err == io.EOF || arg[0] == 0 {
 | |
| 			break
 | |
| 		}
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		args = append(args, string(chop(arg)))
 | |
| 	}
 | |
| 
 | |
| 	self.List = args
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Get returns the environment of a process
 | |
| func (self *ProcEnv) Get(pid int) error {
 | |
| 	if self.Vars == nil {
 | |
| 		self.Vars = map[string]string{}
 | |
| 	}
 | |
| 
 | |
| 	/* If buffer is not large enough, args are truncated */
 | |
| 	buf := make([]byte, 8192)
 | |
| 	info := C.struct_procsinfo64{}
 | |
| 	info.pi_pid = C.pid_t(pid)
 | |
| 
 | |
| 	if _, err := C.getevars(unsafe.Pointer(&info), C.sizeof_struct_procsinfo64, (*C.char)(&buf[0]), 8192); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	bbuf := bytes.NewBuffer(buf)
 | |
| 
 | |
| 	delim := []byte{61} // "="
 | |
| 
 | |
| 	for {
 | |
| 		line, err := bbuf.ReadBytes(0)
 | |
| 		if err == io.EOF || line[0] == 0 {
 | |
| 			break
 | |
| 		}
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		pair := bytes.SplitN(chop(line), delim, 2)
 | |
| 		if len(pair) != 2 {
 | |
| 			return fmt.Errorf("Error reading process environment for PID: %d", pid)
 | |
| 		}
 | |
| 		self.Vars[string(pair[0])] = string(pair[1])
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Get returns the path of the process executable
 | |
| func (self *ProcExe) Get(pid int) error {
 | |
| 	/* If buffer is not large enough, args are truncated */
 | |
| 	buf := make([]byte, 8192)
 | |
| 	info := C.struct_procsinfo64{}
 | |
| 	info.pi_pid = C.pid_t(pid)
 | |
| 
 | |
| 	if _, err := C.getargs(unsafe.Pointer(&info), C.sizeof_struct_procsinfo64, (*C.char)(&buf[0]), 8192); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	bbuf := bytes.NewBuffer(buf)
 | |
| 
 | |
| 	// retrieve the first argument
 | |
| 	cmd, err := bbuf.ReadBytes(0)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	self.Name = string(chop(cmd))
 | |
| 
 | |
| 	cwd, err := os.Readlink("/proc/" + strconv.Itoa(pid) + "/cwd")
 | |
| 	if err != nil {
 | |
| 		if !os.IsNotExist(err) {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 	self.Cwd = cwd
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Get returns process filesystem usage. Not implimented on AIX.
 | |
| func (*ProcFDUsage) Get(_ int) error {
 | |
| 	return ErrNotImplemented{runtime.GOOS}
 | |
| }
 | |
| 
 | |
| // Get returns filesytem usage. Not implimented on AIX.
 | |
| func (*FDUsage) Get() error {
 | |
| 	return ErrNotImplemented{runtime.GOOS}
 | |
| }
 | |
| 
 | |
| // Get returns huge pages info. Not implimented on AIX.
 | |
| func (*HugeTLBPages) Get() error {
 | |
| 	return ErrNotImplemented{runtime.GOOS}
 | |
| }
 |