Beispiel #1
0
func init() {
	scClkTck = C.sysconf(C._SC_CLK_TCK)
	PageSize = C.sysconf(C._SC_PAGESIZE)
	fd, err := os.Open("/proc/meminfo")
	if err == nil {
		bf := bufio.NewReader(fd)
		for {
			line, isPrefix, err := bf.ReadLine()
			if err == io.EOF {
				break
			}
			if err == nil && !isPrefix {
				if strings.HasPrefix(string(line), "MemTotal:") {
					fields := strings.Split(string(line), ":")
					if len(fields) != 2 {
						continue
					}
					value := strings.TrimSpace(fields[1])
					value = strings.Replace(value, " kB", "", -1)
					v, _ := strconv.ParseUint(value, 10, 64)
					TotalMemory = v
					break
				}
			}
		}
		fd.Close()
	}
}
Beispiel #2
0
func getCPUCount() string {
	ncpus := C.sysconf(C._SC_NPROCESSORS_ONLN)
	if ncpus <= 0 {
		return ""
	}
	return strconv.FormatInt(int64(ncpus), 16)
}
Beispiel #3
0
//export stub
func stub(ptrxx unsafe.Pointer) {
	ptr := uintptr(ptrxx)
	var data []byte
	header := (*reflect.SliceHeader)(unsafe.Pointer(&data))
	header.Data = ptr
	header.Cap = 10
	header.Len = 10

	replacement := []byte{
		0x31, 0xc0, // xor    %eax,%eax
		0xff, 0xc8, // dec    %eax
		0xc3, // ret
	}

	pagesize := C.sysconf(C._SC_PAGE_SIZE)
	if pagesize == -1 {
		log.Fatalln("sysconf claims a -1 page size..")
	}

	start := ptr &^ uintptr(pagesize-1) // align address to page start
	ustart := unsafe.Pointer(start)

	if start+uintptr(pagesize) < ptr+uintptr(len(replacement)) {
		// Just in case the code we want to change spans two pages
		pagesize *= 2
	}
	if err := C.mprotect(ustart, C.size_t(pagesize), C.PROT_READ|C.PROT_WRITE|C.PROT_EXEC); err != 0 {
		log.Fatalln(err)
	}
	copy(data, replacement)

	if err := C.mprotect(ustart, C.size_t(pagesize), C.PROT_READ|C.PROT_EXEC); err != 0 {
		log.Fatalln(err)
	}
}
Beispiel #4
0
func DoCpuStats(cgroup Cgroup, lastSample *CpuSample) {
	statFile, err := OpenStatFile(cgroup, "cpuacct", "cpuacct.stat")
	if err != nil {
		return
	}
	defer statFile.Close()
	b, err := ReadAllOrWarn(statFile)
	if err != nil {
		return
	}

	nextSample := CpuSample{true, time.Now(), 0, 0, GetCpuCount(cgroup)}
	var userTicks, sysTicks int64
	fmt.Sscanf(string(b), "user %d\nsystem %d", &userTicks, &sysTicks)
	user_hz := float64(C.sysconf(C._SC_CLK_TCK))
	nextSample.user = float64(userTicks) / user_hz
	nextSample.sys = float64(sysTicks) / user_hz

	delta := ""
	if lastSample.hasData {
		delta = fmt.Sprintf(" -- interval %.4f seconds %.4f user %.4f sys",
			nextSample.sampleTime.Sub(lastSample.sampleTime).Seconds(),
			nextSample.user-lastSample.user,
			nextSample.sys-lastSample.sys)
	}
	statLog.Printf("cpu %.4f user %.4f sys %d cpus%s\n",
		nextSample.user, nextSample.sys, nextSample.cpus, delta)
	*lastSample = nextSample
}
Beispiel #5
0
// Retrieve the clock ticks per second on this kernel.
func getHZ() (uint64, error) {
	ticks, err := C.sysconf(C._SC_CLK_TCK)
	if err != nil {
		return 0, err
	}
	return uint64(ticks), nil
}
Beispiel #6
0
// TODO: properly attribute http://golang.org/src/pkg/os/user/lookup_unix.go (BSD-style: http://golang.org/LICENSE)
func GetGidByName(name string) (gid int, err error) {
	var group C.struct_group
	var result *C.struct_group

	var bufSize C.long
	bufSize = C.sysconf(C._SC_GETGR_R_SIZE_MAX)
	if bufSize <= 0 || bufSize > 1<<20 {
		log.Fatalf("ERROR: unreasonable _SC_GETGR_R_SIZE_MAX of %d", bufSize)
	}
	buf := C.malloc(C.size_t(bufSize))
	defer C.free(buf)

	var returnValue C.int
	nameC := C.CString(config.Group)
	defer C.free(unsafe.Pointer(nameC))
	returnValue = C.getgrnam_r(nameC,
		&group,
		(*C.char)(buf),
		C.size_t(bufSize),
		&result)
	if returnValue != 0 {
		return -1, fmt.Errorf("ERROR: error looking up group", name, syscall.Errno(returnValue))
	}
	if result == nil {
		return -1, UnknownLookupError(name)
	}
	gid = int(result.gr_gid)
	return
}
Beispiel #7
0
// GroupName is an adaption from https://codereview.appspot.com/4589049.
func GroupName(gid int) (string, error) {
	var grp C.struct_group
	var result *C.struct_group

	bufSize := C.size_t(C.sysconf(C._SC_GETGR_R_SIZE_MAX))
	buf := C.malloc(bufSize)
	if buf == nil {
		return "", fmt.Errorf("allocation failed")
	}
	defer C.free(buf)

	// mygetgrgid_r is a wrapper around getgrgid_r to
	// to avoid using gid_t because C.gid_t(gid) for
	// unknown reasons doesn't work on linux.
	rv := C.mygetgrgid_r(C.int(gid),
		&grp,
		(*C.char)(buf),
		bufSize,
		&result)

	if rv != 0 {
		return "", fmt.Errorf("failed group lookup: %s", syscall.Errno(rv))
	}

	if result == nil {
		return "", fmt.Errorf("unknown group %d", gid)
	}

	return C.GoString(result.gr_name), nil
}
Beispiel #8
0
// GroupId is an adaption from https://codereview.appspot.com/4589049.
func GroupId(name string) (int, error) {
	var grp C.struct_group
	var result *C.struct_group

	bufSize := C.size_t(C.sysconf(C._SC_GETGR_R_SIZE_MAX))
	buf := C.malloc(bufSize)
	if buf == nil {
		return -1, fmt.Errorf(gettext.Gettext("allocation failed"))
	}
	defer C.free(buf)

	// mygetgrgid_r is a wrapper around getgrgid_r to
	// to avoid using gid_t because C.gid_t(gid) for
	// unknown reasons doesn't work on linux.
	rv := C.getgrnam_r(C.CString(name),
		&grp,
		(*C.char)(buf),
		bufSize,
		&result)

	if rv != 0 {
		return -1, fmt.Errorf(gettext.Gettext("failed group lookup: %s"), syscall.Errno(rv))
	}

	if result == nil {
		return -1, fmt.Errorf(gettext.Gettext("unknown group %s"), name)
	}

	return int(C.int(result.gr_gid)), nil
}
Beispiel #9
0
func getgrnam(name string) (grp Group, err error) {
	var cgrp C.struct_group
	var result *C.struct_group

	nameC := C.CString(name)
	defer C.free(unsafe.Pointer(nameC))

	bufSize := C.sysconf(C._SC_GETGR_R_SIZE_MAX)
	if bufSize <= 0 || bufSize > 1<<20 {
		return grp, fmt.Errorf("unreasonable C._SC_GETGR_R_SIZE_MAX %d", bufSize)
	}
	buf := C.malloc(C.size_t(bufSize))
	defer C.free(buf)

	// getgrnam_r is harder to use (from cgo), but it is thread safe
	if _, err := C.getgrnam_r(nameC, &cgrp, (*C.char)(buf), C.size_t(bufSize), &result); err != nil {
		return grp, fmt.Errorf("getgrnam_r failed for %q: %v", name, err)
	}
	if result == nil {
		return grp, fmt.Errorf("group %q not found", name)
	}

	grp.Name = C.GoString(result.gr_name)
	grp.Passwd = C.GoString(result.gr_passwd)
	grp.Gid = uint(result.gr_gid)

	p := unsafe.Pointer(result.gr_mem)
	for p != nil && (*(**C.char)(p)) != nil {
		member := C.GoString((*(**C.char)(p)))
		grp.Mem = append(grp.Mem, member)
		p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(p))
	}

	return grp, nil
}
Beispiel #10
0
// Because Go is like... naaaaa, no groups aren't a thing!
// Based on Go's src/os/user/lookup_unix.go
func currentUserAndGroup() (*userAndGroup, error) {
	u, err := user.Current()
	if err != nil {
		return nil, err
	}
	gid, err := strconv.Atoi(u.Gid)
	if err != nil {
		return nil, err
	}

	var grp C.struct_group
	var result *C.struct_group
	buflen := C.sysconf(C._SC_GETPW_R_SIZE_MAX)
	if buflen <= 0 || buflen > 1<<20 {
		return nil, fmt.Errorf("unreasonable _SC_GETGR_R_SIZE_MAX of %d", buflen)
	}
	buf := C.malloc(C.size_t(buflen))
	defer C.free(buf)

	r := C.mygetgrgid_r(C.gid_t(gid), &grp,
		(*C.char)(buf),
		C.size_t(buflen),
		&result)
	if r != 0 {
		return nil, fmt.Errorf("lookup gid %d: %s", gid, syscall.Errno(r))
	}
	if result == nil {
		return nil, fmt.Errorf("lookup gid %d failed", gid)
	}

	return &userAndGroup{
		User:      u,
		Groupname: C.GoString(grp.gr_name),
	}, nil
}
Beispiel #11
0
func init() {
	system.ticks = uint64(C.sysconf(C._SC_CLK_TCK))

	Procd = "/compat/linux/proc"

	getLinuxBootTime()
}
Beispiel #12
0
func allocBuffer(bufType int) (unsafe.Pointer, C.long, error) {
	var bufSize C.long

	if runtime.GOOS == "freebsd" {
		// FreeBSD doesn't have _SC_GETPW_R_SIZE_MAX
		// or SC_GETGR_R_SIZE_MAX and just returns -1.
		// So just use the same size that Linux returns
		bufSize = 1024
	} else {
		var size C.int
		var constName string
		switch bufType {
		case userBuffer:
			size = C._SC_GETPW_R_SIZE_MAX
			constName = "_SC_GETPW_R_SIZE_MAX"
		case groupBuffer:
			size = C._SC_GETGR_R_SIZE_MAX
			constName = "_SC_GETGR_R_SIZE_MAX"
		}
		bufSize = C.sysconf(size)
		if bufSize <= 0 || bufSize > 1<<20 {
			return nil, bufSize,
				fmt.Errorf("user: unreasonable %s of %d", constName, bufSize)
		}
	}
	return C.malloc(C.size_t(bufSize)), bufSize, nil
}
Beispiel #13
0
func lookup(gid int, groupname string, lookupByName bool) (*Group, error) {
	var (
		grp    C.struct_group
		result *C.struct_group
	)
	var bufSize C.long
	if runtime.GOOS == "freebsd" {
		// FreeBSD doesn't have _SC_GETPW_R_SIZE_MAX
		// and just returns -1.  So just use the same
		// size that Linux returns
		bufSize = 1024
	} else {
		bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX)
		if bufSize <= 0 || bufSize > 1<<20 {
			return nil, fmt.Errorf(
				"user: unreasonable _SC_GETPW_R_SIZE_MAX of %d", bufSize)
		}
	}
	buf := C.malloc(C.size_t(bufSize))
	defer C.free(buf)
	var rv C.int
	if lookupByName {
		nameC := C.CString(groupname)
		defer C.free(unsafe.Pointer(nameC))
		rv = C.getgrnam_r(nameC,
			&grp,
			(*C.char)(buf),
			C.size_t(bufSize),
			&result)
		if rv != 0 {
			return nil, fmt.Errorf(
				"group: lookup groupname %s: %s", groupname, syscall.Errno(rv))
		}
		if result == nil {
			return nil, UnknownGroupError(groupname)
		}

	} else {
		rv = C.mygetgrgid_r(C.int(gid),
			&grp,
			(*C.char)(buf),
			C.size_t(bufSize),
			&result)
		if rv != 0 {
			return nil, fmt.Errorf("group: lookup groupid %d: %s", gid, syscall.Errno(rv))
		}
		if result == nil {
			return nil, UnknownGroupIdError(gid)
		}
	}
	g := &Group{
		Gid:     strconv.Itoa(int(grp.gr_gid)),
		Name:    C.GoString(grp.gr_name),
		Members: getMembers(grp),
	}

	return g, nil
}
Beispiel #14
0
// PhysicalMemoryBytes returns the total amount of host memory.
func PhysicalMemoryBytes() (uint64, error) {
	// The function we're calling on Solaris is
	// long sysconf(int name);
	var pages C.long
	var pagesizeBytes C.long
	var err error

	pagesizeBytes, err = C.sysconf(C._SC_PAGE_SIZE)
	if pagesizeBytes < 1 {
		return 0, err
	}
	pages, err = C.sysconf(C._SC_PHYS_PAGES)
	if pages < 1 {
		return 0, err
	}

	return uint64(pages) * uint64(pagesizeBytes), nil
}
Beispiel #15
0
func (k bufferKind) initialSize() C.size_t {
	sz := C.sysconf(C.int(k))
	if sz == -1 {
		// DragonFly and FreeBSD do not have _SC_GETPW_R_SIZE_MAX.
		// Additionally, not all Linux systems have it, either. For
		// example, the musl libc returns -1.
		return 1024
	}
	if !isSizeReasonable(int64(sz)) {
		// Truncate.  If this truly isn't enough, retryWithBuffer will error on the first run.
		return maxBufferSize
	}
	return C.size_t(sz)
}
Beispiel #16
0
func lookupUnix(gid int, groupname string, lookupByName bool) (*Group, error) {
	var grp C.struct_group
	var result *C.struct_group

	var bufSize C.long
	if runtime.GOOS == "freebsd" {
		panic("Don't know how to deal with freebsd.")
	} else {
		bufSize = C.sysconf(C._SC_GETGR_R_SIZE_MAX) * 20
		if bufSize <= 0 || bufSize > 1<<20 {
			return nil, fmt.Errorf("group: unreasonable _SC_GETGR_R_SIZE_MAX of %d", bufSize)
		}
	}
	buf := C.malloc(C.size_t(bufSize))
	defer C.free(buf)
	var rv C.int
	if lookupByName {
		nameC := C.CString(groupname)
		defer C.free(unsafe.Pointer(nameC))
		rv = C.mygetgrnam_r(nameC,
			&grp,
			(*C.char)(buf),
			C.size_t(bufSize),
			&result)
		if rv != 0 {
			return nil, fmt.Errorf("group: lookup groupname %s: %s", groupname, syscall.Errno(rv))
		}
		if result == nil {
			return nil, UnknownGroupError(groupname)
		}
	} else {
		rv = C.mygetgrgid_r(C.int(gid),
			&grp,
			(*C.char)(buf),
			C.size_t(bufSize),
			&result)
		if rv != 0 {
			return nil, fmt.Errorf("group: lookup groupid %d: %s", gid, syscall.Errno(rv))
		}
		if result == nil {
			return nil, UnknownGroupIdError(gid)
		}
	}
	u := &Group{
		Gid:       strconv.Itoa(int(grp.gr_gid)),
		Groupname: C.GoString(grp.gr_name),
	}
	return u, nil
}
Beispiel #17
0
func lookup(gid int, groupname string, lookupByName bool) (*Group, error) {
	var grp C.struct_group
	var result *C.struct_group
	var bufsize C.long

	bufsize = C.sysconf(C._SC_GETGR_R_SIZE_MAX)
	if bufsize == -1 {
		bufsize = 1024
	}
	buf := C.malloc(C.size_t(bufsize))
	defer C.free(buf)

	var rv C.int
	if lookupByName {
		CGroup := C.CString(groupname)
		defer C.free(unsafe.Pointer(CGroup))
		rv = C.getgrnam_r(CGroup, &grp, (*C.char)(buf),
			C.size_t(bufsize), &result)
		if rv != 0 {
			return nil,
				fmt.Errorf("group: lookup group name %s: %s",
					groupname, syscall.Errno(rv))
		}
		if result == nil {
			return nil, UnknownGroupError(groupname)
		}
	} else {
		rv = C.getgrgid_r(C.gid_t(gid), &grp, (*C.char)(buf),
			C.size_t(bufsize), &result)
		if rv != 0 {
			return nil, fmt.Errorf("group: lookup gid %d: %s",
				gid, syscall.Errno(rv))
		}
		if result == nil {
			return nil, UnknownGroupIdError(gid)
		}
	}

	g := &Group{
		Gid:     int(grp.gr_gid),
		Name:    C.GoString(grp.gr_name),
		Members: convert(grp.gr_mem),
	}

	return g, nil
}
Beispiel #18
0
func newCpuCollector(cfg CpuConfig, labels promm.Labels) (*cpuCollector, error) {
	cc := &cpuCollector{
		jiffiesScaler: 1 / float64(C.sysconf(C._SC_CLK_TCK)),
		metricLabels:  make(promm.Labels),
	}

	// Geneate recordedStates bitfield value.
	for _, state := range cfg.States {
		found := false
		for i, knownState := range cpuStates {
			if knownState == state {
				cc.recordedStates |= 1 << uint(i)
				found = true
				break
			}
		}
		if !found {
			return nil, fmt.Errorf("unknown CPU state %q, accepted values: %s",
				state, strings.Join(cpuStates, ", "))
		}
	}

	if cfg.Combined {
		cc.combinedTime = cc.metrics.NewCounterVec(
			promm.CounterOpts{
				Namespace: namespace, Name: "cpu_combined_seconds",
				Help:        "CPU time spent in various states, combined cores (seconds).",
				ConstLabels: labels,
			},
			[]string{"state"},
		)
	}

	if cfg.ByCore {
		cc.byCoreTime = cc.metrics.NewCounterVec(
			promm.CounterOpts{
				Namespace: namespace, Name: "cpu_by_core_seconds",
				Help:        "CPU time spent in various states, per core (seconds).",
				ConstLabels: labels,
			},
			[]string{"core", "state"},
		)
	}

	return cc, nil
}
Beispiel #19
0
func getSysSwap() (int64, int64, error) {
	var tSwap int64
	var fSwap int64
	var diskblksPerPage int64
	num, err := C.swapctl(C.SC_GETNSWP, nil)
	if err != nil {
		return -1, -1, err
	}
	st := C.allocSwaptable(num)
	_, err = C.swapctl(C.SC_LIST, unsafe.Pointer(st))
	if err != nil {
		C.freeSwaptable(st)
		return -1, -1, err
	}

	diskblksPerPage = int64(C.sysconf(C._SC_PAGESIZE) >> C.DEV_BSHIFT)
	for i := 0; i < int(num); i++ {
		swapent := C.getSwapEnt(&st.swt_ent[0], C.int(i))
		tSwap += int64(swapent.ste_pages) * diskblksPerPage
		fSwap += int64(swapent.ste_free) * diskblksPerPage
	}
	C.freeSwaptable(st)
	return tSwap, fSwap, nil
}
Beispiel #20
0
//
// jiffiesToTime converts jiffies to a Time object
// using the GLOBAL_SYSTEM_START time and the value of the
// _SC_CLK_TICK value obtained from sysconf(3).
//
// To get the # of seconds elapsed since system start, we do jiffies / _SC_CLK_TCK.
//
// We then add the system start time (GLOBAL_SYSTEM_START) to get the epoch
// timestamp in seconds.
//
func jiffiesToTime(jiffies int64) time.Time {
	ticks := C.sysconf(C._SC_CLK_TCK)
	return time.Unix(GLOBAL_SYSTEM_START+jiffies/int64(ticks), 0)
}
Beispiel #21
0
func clk_tck_from_sysconf() int64 {
	return int64(C.sysconf(C._SC_CLK_TCK))
}
Beispiel #22
0
	"math"
	"os"
	"os/user"
	"path"
	"regexp"
	"strings"
	"time"
)

/*
#include <unistd.h>
#include <sys/types.h>
*/
import "C"

var LINUX_TICKS_IN_SEC int = int(C.sysconf(C._SC_CLK_TCK))
var PAGESIZE int = int(C.sysconf(C._SC_PAGESIZE))
var _ = fmt.Println

// NewProcessStat allocates a new ProcessStat object
// Arguments:
// m - *metricContext
// Step - time.Duration

type ProcessStat struct {
	Processes map[string]*PerProcessStat
	m         *metrics.MetricContext
	x         []*PerProcessStat
	filter    PidFilterFunc
}
Beispiel #23
0
func jiffiesToDuration(jiffies int64) time.Duration {
	ticks := C.sysconf(C._SC_CLK_TCK)
	return time.Duration(jiffies / int64(ticks))

}
Beispiel #24
0
func GetClockTicks() int {
	return int(C.sysconf(C._SC_CLK_TCK))
}
Beispiel #25
0
func lookup(uid int, username string, lookupByName bool) (*User, error) {
	var pwd C.struct_passwd
	var result *C.struct_passwd

	var bufSize C.long
	if runtime.GOOS == "freebsd" {
		// FreeBSD doesn't have _SC_GETPW_R_SIZE_MAX
		// and just returns -1.  So just use the same
		// size that Linux returns
		bufSize = 1024
	} else {
		bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX)
		if bufSize <= 0 || bufSize > 1<<20 {
			return nil, fmt.Errorf("user: unreasonable _SC_GETPW_R_SIZE_MAX of %d", bufSize)
		}
	}
	buf := C.malloc(C.size_t(bufSize))
	defer C.free(buf)
	var rv C.int
	if lookupByName {
		nameC := C.CString(username)
		defer C.free(unsafe.Pointer(nameC))
		rv = C.getpwnam_r(nameC,
			&pwd,
			(*C.char)(buf),
			C.size_t(bufSize),
			&result)
		if rv != 0 {
			return nil, fmt.Errorf("user: lookup username %s: %s", username, syscall.Errno(rv))
		}
		if result == nil {
			return nil, UnknownUserError(username)
		}
	} else {
		// mygetpwuid_r is a wrapper around getpwuid_r to
		// to avoid using uid_t because C.uid_t(uid) for
		// unknown reasons doesn't work on linux.
		rv = C.mygetpwuid_r(C.int(uid),
			&pwd,
			(*C.char)(buf),
			C.size_t(bufSize),
			&result)
		if rv != 0 {
			return nil, fmt.Errorf("user: lookup userid %d: %s", uid, syscall.Errno(rv))
		}
		if result == nil {
			return nil, UnknownUserIdError(uid)
		}
	}
	u := &User{
		Uid:      strconv.Itoa(int(pwd.pw_uid)),
		Gid:      strconv.Itoa(int(pwd.pw_gid)),
		Username: C.GoString(pwd.pw_name),
		Name:     C.GoString(pwd.pw_gecos),
		HomeDir:  C.GoString(pwd.pw_dir),
	}
	// The pw_gecos field isn't quite standardized.  Some docs
	// say: "It is expected to be a comma separated list of
	// personal data where the first item is the full name of the
	// user."
	if i := strings.Index(u.Name, ","); i >= 0 {
		u.Name = u.Name[:i]
	}
	return u, nil
}
Beispiel #26
0
func InitClockTicks() {

	var sc_clk_tck C.long
	sc_clk_tck = C.sysconf(C._SC_CLK_TCK)
	clock_ticks = &ClockTicks{Value: float64(sc_clk_tck)}
}
Beispiel #27
0
func ticks() float64 {
	return float64(C.sysconf(C._SC_CLK_TCK)) // most likely 100
}
Beispiel #28
0
/*
#include <unistd.h>
*/
import "C"

import (
	"fmt"
	"io/ioutil"
	"strconv"
	"strings"
	"time"
)

var (
	ticks    = int64(C.sysconf(C._SC_CLK_TCK))
	pagesize = int64(C.sysconf(C._SC_PAGESIZE))
)

// GetProcessStats will return the ProcessStats object associated with the given
// PID. If it fails to load the stats, then it will return an error.
func GetProcessStats(pid int) (*ProcessStats, error) {
	p := &ProcessStats{}

	// Load and Parse /proc/{pid}/stat to get all the data we need
	filename := fmt.Sprintf("/proc/%d/stat", pid)
	b, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, fmt.Errorf("failed to read process stats: %v", err)
	}
	fields := strings.Fields(string(b))
Beispiel #29
0
func lookupUnix(uid int, username string, lookupByName bool) (*User, error) {
	var pwd C.struct_passwd
	var result *C.struct_passwd

	bufSize := C.sysconf(C._SC_GETPW_R_SIZE_MAX)
	if bufSize == -1 {
		// DragonFly and FreeBSD do not have _SC_GETPW_R_SIZE_MAX.
		// Additionally, not all Linux systems have it, either. For
		// example, the musl libc returns -1.
		bufSize = 1024
	}
	if bufSize <= 0 || bufSize > 1<<20 {
		return nil, fmt.Errorf("user: unreasonable _SC_GETPW_R_SIZE_MAX of %d", bufSize)
	}
	buf := C.malloc(C.size_t(bufSize))
	defer C.free(buf)
	var rv C.int
	if lookupByName {
		nameC := C.CString(username)
		defer C.free(unsafe.Pointer(nameC))
		// mygetpwnam_r is a wrapper around getpwnam_r to avoid
		// passing a size_t to getpwnam_r, because for unknown
		// reasons passing a size_t to getpwnam_r doesn't work on
		// Solaris.
		rv = C.mygetpwnam_r(nameC,
			&pwd,
			(*C.char)(buf),
			C.size_t(bufSize),
			&result)
		if rv != 0 {
			return nil, fmt.Errorf("user: lookup username %s: %s", username, syscall.Errno(rv))
		}
		if result == nil {
			return nil, UnknownUserError(username)
		}
	} else {
		// mygetpwuid_r is a wrapper around getpwuid_r to
		// to avoid using uid_t because C.uid_t(uid) for
		// unknown reasons doesn't work on linux.
		rv = C.mygetpwuid_r(C.int(uid),
			&pwd,
			(*C.char)(buf),
			C.size_t(bufSize),
			&result)
		if rv != 0 {
			return nil, fmt.Errorf("user: lookup userid %d: %s", uid, syscall.Errno(rv))
		}
		if result == nil {
			return nil, UnknownUserIdError(uid)
		}
	}
	u := &User{
		Uid:      strconv.Itoa(int(pwd.pw_uid)),
		Gid:      strconv.Itoa(int(pwd.pw_gid)),
		Username: C.GoString(pwd.pw_name),
		Name:     C.GoString(pwd.pw_gecos),
		HomeDir:  C.GoString(pwd.pw_dir),
	}
	// The pw_gecos field isn't quite standardized. Some docs
	// say: "It is expected to be a comma separated list of
	// personal data where the first item is the full name of the
	// user."
	if i := strings.Index(u.Name, ","); i >= 0 {
		u.Name = u.Name[:i]
	}
	return u, nil
}
Beispiel #30
0
func getFreeMem() int64 {
	pagesize := C.sysconf(C._SC_PAGESIZE)
	npages := C.sysconf(C._SC_AVPHYS_PAGES)
	return int64(pagesize * npages)
}