2004-06-22 06:37:04 +08:00
|
|
|
#include "sigar.h"
|
|
|
|
#include "sigar_private.h"
|
|
|
|
#include "sigar_os.h"
|
|
|
|
#include "sigar_util.h"
|
|
|
|
|
|
|
|
#include <sys/proc.h>
|
|
|
|
#include <sys/swap.h>
|
|
|
|
|
|
|
|
#define KSTAT_LIST_INIT(sigar, dev) \
|
|
|
|
sigar->koffsets.dev[0] = -1; \
|
|
|
|
sigar->ks.dev.num = 0; \
|
|
|
|
sigar->ks.dev.ks = NULL; \
|
|
|
|
sigar->ks.dev.name = #dev; \
|
|
|
|
sigar->ks.dev.nlen = strlen(#dev)
|
|
|
|
|
|
|
|
int sigar_os_open(sigar_t **sig)
|
|
|
|
{
|
|
|
|
kstat_ctl_t *kc;
|
|
|
|
kstat_t *ksp;
|
|
|
|
sigar_t *sigar;
|
|
|
|
int i, status;
|
|
|
|
|
|
|
|
sigar = malloc(sizeof(*sigar));
|
|
|
|
*sig = sigar;
|
|
|
|
|
|
|
|
sigar->pagesize = 0;
|
|
|
|
i = sysconf(_SC_PAGESIZE);
|
|
|
|
while ((i >>= 1) > 0) {
|
|
|
|
sigar->pagesize++;
|
|
|
|
}
|
|
|
|
|
|
|
|
sigar->ticks = sysconf(_SC_CLK_TCK);
|
|
|
|
sigar->kc = kc = kstat_open();
|
|
|
|
|
|
|
|
if (!kc) {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
2004-06-22 09:29:47 +08:00
|
|
|
sigar->cpulist.size = 0;
|
2004-06-22 06:37:04 +08:00
|
|
|
sigar->ncpu = 0;
|
|
|
|
sigar->ks.cpu = NULL;
|
|
|
|
sigar->ks.cpuid = NULL;
|
|
|
|
sigar->ks.lcpu = 0;
|
|
|
|
|
|
|
|
KSTAT_LIST_INIT(sigar, lo);
|
|
|
|
KSTAT_LIST_INIT(sigar, hme);
|
|
|
|
KSTAT_LIST_INIT(sigar, dmfe);
|
|
|
|
KSTAT_LIST_INIT(sigar, ge);
|
|
|
|
KSTAT_LIST_INIT(sigar, eri);
|
|
|
|
|
|
|
|
sigar->vminfo_snaptime = 0;
|
|
|
|
|
|
|
|
sigar->koffsets.system[0] = -1;
|
|
|
|
sigar->koffsets.mempages[0] = -1;
|
|
|
|
sigar->koffsets.syspages[0] = -1;
|
|
|
|
|
|
|
|
if ((status = sigar_get_kstats(sigar)) != SIGAR_OK) {
|
|
|
|
fprintf(stderr, "status=%d\n", status);
|
|
|
|
}
|
|
|
|
|
|
|
|
sigar->boot_time = 0;
|
|
|
|
|
|
|
|
if ((ksp = sigar->ks.system) &&
|
|
|
|
(kstat_read(kc, ksp, NULL) >= 0))
|
|
|
|
{
|
|
|
|
sigar_koffsets_init_system(sigar, ksp);
|
|
|
|
|
|
|
|
sigar->boot_time = kSYSTEM(KSTAT_SYSTEM_BOOT_TIME);
|
|
|
|
}
|
|
|
|
|
|
|
|
sigar->last_pid = -1;
|
|
|
|
sigar->pinfo = NULL;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_os_close(sigar_t *sigar)
|
|
|
|
{
|
|
|
|
kstat_close(sigar->kc);
|
|
|
|
|
|
|
|
if (sigar->ks.lo.num) {
|
|
|
|
free(sigar->ks.lo.ks);
|
|
|
|
}
|
|
|
|
if (sigar->ks.hme.num) {
|
|
|
|
free(sigar->ks.hme.ks);
|
|
|
|
}
|
|
|
|
if (sigar->ks.dmfe.num) {
|
|
|
|
free(sigar->ks.dmfe.ks);
|
|
|
|
}
|
|
|
|
if (sigar->ks.ge.num) {
|
|
|
|
free(sigar->ks.ge.ks);
|
|
|
|
}
|
|
|
|
if (sigar->ks.eri.num) {
|
|
|
|
free(sigar->ks.eri.ks);
|
|
|
|
}
|
|
|
|
if (sigar->ks.lcpu) {
|
|
|
|
free(sigar->ks.cpu);
|
|
|
|
free(sigar->ks.cpuid);
|
|
|
|
}
|
|
|
|
if (sigar->pinfo) {
|
|
|
|
free(sigar->pinfo);
|
|
|
|
}
|
2004-06-22 09:29:47 +08:00
|
|
|
if (sigar->cpulist.size != 0) {
|
|
|
|
sigar_cpu_list_destroy(sigar, &sigar->cpulist);
|
|
|
|
}
|
2004-06-22 06:37:04 +08:00
|
|
|
free(sigar);
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *sigar_os_error_string(int err)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static SIGAR_INLINE int sigar_kstat_update(sigar_t *sigar)
|
|
|
|
{
|
|
|
|
switch (kstat_chain_update(sigar->kc)) {
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
case -1:
|
|
|
|
return -1; /* shouldn't happen */
|
|
|
|
default:
|
|
|
|
sigar_get_kstats(sigar);
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define KPAGE_SHIFT(v) \
|
|
|
|
((v) << sigar->pagesize)
|
|
|
|
|
|
|
|
int sigar_mem_get(sigar_t *sigar, sigar_mem_t *mem)
|
|
|
|
{
|
|
|
|
kstat_ctl_t *kc = sigar->kc;
|
|
|
|
kstat_t *ksp;
|
|
|
|
|
|
|
|
SIGAR_ZERO(mem);
|
|
|
|
|
|
|
|
/* XXX: is mem hot swappable or can we just do this during open ? */
|
|
|
|
mem->total = KPAGE_SHIFT((sigar_uint64_t)sysconf(_SC_PHYS_PAGES));
|
|
|
|
|
|
|
|
sigar_mem_calc_ram(sigar, mem);
|
|
|
|
|
|
|
|
sigar_kstat_update(sigar);
|
|
|
|
|
|
|
|
if ((ksp = sigar->ks.syspages) && kstat_read(kc, ksp, NULL) >= 0) {
|
|
|
|
sigar_koffsets_init_syspages(sigar, ksp);
|
|
|
|
|
|
|
|
mem->free = KPAGE_SHIFT(kSYSPAGES(KSTAT_SYSPAGES_FREE));
|
|
|
|
|
|
|
|
mem->used = mem->total - mem->free;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ksp = sigar->ks.mempages) && kstat_read(kc, ksp, NULL) >= 0) {
|
|
|
|
sigar_koffsets_init_mempages(sigar, ksp);
|
|
|
|
|
|
|
|
mem->shared = KPAGE_SHIFT(kMEMPAGES(KSTAT_MEMPAGES_EXEC));
|
|
|
|
|
|
|
|
mem->buffer = KPAGE_SHIFT(kMEMPAGES(KSTAT_MEMPAGES_VNODE));
|
|
|
|
|
|
|
|
mem->cached = -1; /*XXX*/
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_swap_get(sigar_t *sigar, sigar_swap_t *swap)
|
|
|
|
{
|
|
|
|
#if defined(SIGAR_SWAP_KSTAT)
|
|
|
|
kstat_ctl_t *kc = sigar->kc;
|
|
|
|
kstat_t *ksp;
|
|
|
|
vminfo_t vminfo;
|
|
|
|
|
|
|
|
sigar_kstat_update(sigar);
|
|
|
|
|
|
|
|
if ((ksp = sigar->ks.vminfo) && kstat_read(kc, ksp, &vminfo) >= 0) {
|
|
|
|
/* XXX: need some adjustments here */
|
|
|
|
swap->total = vminfo.swap_resv + vminfo.swap_avail;
|
|
|
|
swap->used = vminfo.swap_alloc;
|
|
|
|
swap->free = swap->total - swap->used;
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
#elif defined(SIGAR_SWAP_SC_LIST)
|
|
|
|
unsigned int i;
|
|
|
|
size_t num;
|
|
|
|
swaptbl_t *stab;
|
|
|
|
char path[256];
|
|
|
|
|
|
|
|
swap->total = swap->used = swap->free = 0;
|
|
|
|
|
|
|
|
num = swapctl(SC_GETNSWP, 0);
|
|
|
|
|
|
|
|
switch (num) {
|
|
|
|
case 0:
|
|
|
|
return SIGAR_OK;
|
|
|
|
case -1:
|
|
|
|
return errno;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
stab = malloc((num * sizeof(swapent_t)) + sizeof(swaptbl_t));
|
|
|
|
|
|
|
|
for (i=0; i<num; i++) {
|
|
|
|
stab->swt_ent[i].ste_path = &path[0]; /* ignored */
|
|
|
|
}
|
|
|
|
|
|
|
|
stab->swt_n = num;
|
|
|
|
num = swapctl(SC_LIST, stab);
|
|
|
|
|
|
|
|
for (i=0; i<num; i++) {
|
|
|
|
swap->total += stab->swt_ent[i].ste_pages;
|
|
|
|
swap->free += stab->swt_ent[i].ste_free;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(stab);
|
|
|
|
|
|
|
|
swap->total <<= sigar->pagesize;
|
|
|
|
swap->free <<= sigar->pagesize;
|
|
|
|
swap->used = swap->total - swap->free;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
#else
|
|
|
|
struct anoninfo anon;
|
|
|
|
|
|
|
|
/* XXX vm/anon.h says:
|
|
|
|
* "The swap data can be aquired more efficiently through the
|
|
|
|
* kstats interface."
|
|
|
|
* but cannot find anything that explains howto convert those numbers.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (swapctl(SC_AINFO, &anon) == -1) {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
swap->total = anon.ani_max;
|
|
|
|
swap->used = anon.ani_resv;
|
|
|
|
swap->free = anon.ani_max - anon.ani_resv;
|
|
|
|
|
|
|
|
swap->total <<= sigar->pagesize;
|
|
|
|
swap->free <<= sigar->pagesize;
|
|
|
|
swap->used <<= sigar->pagesize;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_cpu_get(sigar_t *sigar, sigar_cpu_t *cpu)
|
|
|
|
{
|
|
|
|
int status, i;
|
|
|
|
|
|
|
|
status = sigar_cpu_list_get(sigar, &sigar->cpulist);
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_ZERO(cpu);
|
|
|
|
|
|
|
|
for (i=0; i<sigar->cpulist.number; i++) {
|
|
|
|
sigar_cpu_t *xcpu = &sigar->cpulist.data[i];
|
|
|
|
|
|
|
|
cpu->user += xcpu->user;
|
|
|
|
cpu->sys += xcpu->sys;
|
|
|
|
cpu->idle += xcpu->idle;
|
|
|
|
cpu->nice += xcpu->nice;
|
|
|
|
cpu->total += xcpu->total;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_cpu_list_get(sigar_t *sigar, sigar_cpu_list_t *cpulist)
|
|
|
|
{
|
|
|
|
kstat_ctl_t *kc = sigar->kc;
|
|
|
|
kstat_t *ksp;
|
|
|
|
ulong cpuinfo[CPU_STATES];
|
|
|
|
unsigned int i, n;
|
|
|
|
sigar_kstat_update(sigar);
|
|
|
|
|
2004-06-22 09:29:47 +08:00
|
|
|
if (cpulist == &sigar->cpulist) {
|
|
|
|
if (sigar->cpulist.size == 0) {
|
|
|
|
/* create once */
|
|
|
|
sigar_cpu_list_create(cpulist);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* reset, re-using cpulist.data */
|
|
|
|
sigar->cpulist.number = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2004-06-22 06:37:04 +08:00
|
|
|
sigar_cpu_list_create(cpulist);
|
|
|
|
}
|
2004-06-22 09:29:47 +08:00
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
for (i=0; i<sigar->ncpu; i++) {
|
|
|
|
sigar_cpu_t *cpu;
|
|
|
|
char *buf;
|
|
|
|
|
|
|
|
if (!CPU_ONLINE(sigar->ks.cpuid[i])) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!((ksp = sigar->ks.cpu[i]) &&
|
|
|
|
(kstat_read(kc, ksp, NULL) >= 0)))
|
|
|
|
{
|
|
|
|
continue; /* XXX: shouldnot happen */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* cpu_stat_t is not binary compatible between solaris versions.
|
|
|
|
* since cpu_stat is a 'raw' kstat and not 'named' we cannot
|
|
|
|
* use name based lookups as we do for others.
|
|
|
|
* the start of the cpu_stat_t structure is binary compatible,
|
|
|
|
* which looks like so:
|
|
|
|
* typedef struct cpu_stat {
|
|
|
|
* kmutex_t cpu_stat_lock;
|
|
|
|
* cpu_sysinfo_t cpu_sysinfo;
|
|
|
|
* ...
|
|
|
|
* typedef struct cpu_sysinfo {
|
|
|
|
* ulong cpu[CPU_STATES];
|
|
|
|
* ...
|
|
|
|
* we just copy the piece we need below:
|
|
|
|
*/
|
|
|
|
buf = ksp->ks_data;
|
|
|
|
buf += sizeof(kmutex_t);
|
|
|
|
memcpy(&cpuinfo[0], buf, sizeof(cpuinfo));
|
|
|
|
|
|
|
|
SIGAR_CPU_LIST_GROW(cpulist);
|
|
|
|
|
|
|
|
cpu = &cpulist->data[cpulist->number++];
|
|
|
|
|
|
|
|
cpu->user = cpuinfo[CPU_USER];
|
|
|
|
cpu->sys = cpuinfo[CPU_KERNEL];
|
|
|
|
cpu->idle = cpuinfo[CPU_IDLE];
|
|
|
|
cpu->nice = 0; /* no cpu->nice */
|
|
|
|
cpu->total = 0;
|
|
|
|
|
|
|
|
for (n=0; n<CPU_STATES; n++) {
|
|
|
|
cpu->total += cpuinfo[n];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_uptime_get(sigar_t *sigar,
|
|
|
|
sigar_uptime_t *uptime)
|
|
|
|
{
|
|
|
|
uptime->idletime = 0; /*XXX*/
|
|
|
|
|
|
|
|
if (sigar->boot_time) {
|
|
|
|
uptime->uptime = time(NULL) - sigar->boot_time;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
uptime->uptime = 0; /* XXX: shouldn't happen */
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int loadavg_keys[] = {
|
|
|
|
KSTAT_SYSTEM_LOADAVG_1,
|
|
|
|
KSTAT_SYSTEM_LOADAVG_2,
|
|
|
|
KSTAT_SYSTEM_LOADAVG_3
|
|
|
|
};
|
|
|
|
|
|
|
|
int sigar_loadavg_get(sigar_t *sigar,
|
|
|
|
sigar_loadavg_t *loadavg)
|
|
|
|
{
|
|
|
|
kstat_t *ksp;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
sigar_kstat_update(sigar);
|
|
|
|
|
|
|
|
if (!(ksp = sigar->ks.system)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (kstat_read(sigar->kc, ksp, NULL) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
sigar_koffsets_init_system(sigar, ksp);
|
|
|
|
|
|
|
|
for (i=0; i<3; i++) {
|
|
|
|
loadavg->loadavg[i] = (double)kSYSTEM(loadavg_keys[i]) / FSCALE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_proc_list_get(sigar_t *sigar,
|
|
|
|
sigar_proc_list_t *proclist)
|
|
|
|
{
|
|
|
|
return sigar_proc_list_procfs_get(sigar, proclist);
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_proc_stat_get(sigar_t *sigar,
|
|
|
|
sigar_proc_stat_t *procstat)
|
|
|
|
{
|
|
|
|
int status = /* XXX optimize */
|
|
|
|
sigar_proc_count(sigar, &procstat->total);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
|
|
|
|
sigar_proc_mem_t *procmem)
|
|
|
|
{
|
|
|
|
int status = sigar_proc_psinfo_get(sigar, pid);
|
|
|
|
psinfo_t *pinfo = sigar->pinfo;
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
procmem->size = pinfo->pr_size << 10;
|
|
|
|
procmem->rss = pinfo->pr_rssize << 10;
|
|
|
|
procmem->resident = procmem->rss; /*XXX*/
|
|
|
|
procmem->vsize = procmem->size; /*XXX*/
|
|
|
|
procmem->share = 0; /*XXX*/
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid,
|
|
|
|
sigar_proc_cred_t *proccred)
|
|
|
|
{
|
|
|
|
int status = sigar_proc_psinfo_get(sigar, pid);
|
|
|
|
psinfo_t *pinfo = sigar->pinfo;
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
proccred->uid = pinfo->pr_uid;
|
|
|
|
proccred->gid = pinfo->pr_gid;
|
|
|
|
proccred->euid = pinfo->pr_euid;
|
|
|
|
proccred->egid = pinfo->pr_egid;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define PRTIME_2SIGAR(t) \
|
|
|
|
(t.tv_sec + t.tv_nsec / NANOSEC)
|
|
|
|
|
|
|
|
int sigar_proc_time_get(sigar_t *sigar, sigar_pid_t pid,
|
|
|
|
sigar_proc_time_t *proctime)
|
|
|
|
{
|
|
|
|
prusage_t usage;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
if ((status = sigar_proc_usage_get(sigar, &usage, pid)) != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
proctime->start_time = usage.pr_create.tv_sec + sigar->boot_time;
|
|
|
|
proctime->start_time *= 1000;
|
|
|
|
|
|
|
|
proctime->utime = PRTIME_2SIGAR(usage.pr_utime);
|
|
|
|
proctime->stime = PRTIME_2SIGAR(usage.pr_stime);
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_proc_state_get(sigar_t *sigar, sigar_pid_t pid,
|
|
|
|
sigar_proc_state_t *procstate)
|
|
|
|
{
|
|
|
|
int status = sigar_proc_psinfo_get(sigar, pid);
|
|
|
|
psinfo_t *pinfo = sigar->pinfo;
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_SSTRCPY(procstate->name, pinfo->pr_fname);
|
|
|
|
procstate->ppid = pinfo->pr_ppid;
|
|
|
|
procstate->tty = pinfo->pr_ttydev;
|
|
|
|
procstate->priority = pinfo->pr_lwp.pr_pri;
|
|
|
|
procstate->nice = pinfo->pr_lwp.pr_nice - NZERO;
|
|
|
|
|
|
|
|
switch (pinfo->pr_lwp.pr_state) {
|
|
|
|
case SONPROC:
|
|
|
|
case SRUN:
|
|
|
|
procstate->state = 'R';
|
|
|
|
break;
|
|
|
|
case SZOMB:
|
|
|
|
procstate->state = 'Z';
|
|
|
|
break;
|
|
|
|
case SSLEEP:
|
|
|
|
procstate->state = 'S';
|
|
|
|
break;
|
|
|
|
case SSTOP:
|
|
|
|
procstate->state = 'T';
|
|
|
|
break;
|
|
|
|
case SIDL:
|
|
|
|
procstate->state = 'D';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_proc_args_get(sigar_t *sigar, sigar_pid_t pid,
|
|
|
|
sigar_proc_args_t *procargs)
|
|
|
|
{
|
|
|
|
psinfo_t *pinfo;
|
|
|
|
int fd, status;
|
|
|
|
char buffer[BUFSIZ];
|
|
|
|
char *argvb[56];
|
|
|
|
char *arg, **argvp = argvb;
|
|
|
|
|
|
|
|
int n;
|
|
|
|
size_t nread = 0;
|
|
|
|
unsigned int argv_size;
|
|
|
|
|
|
|
|
if ((status = sigar_proc_psinfo_get(sigar, pid)) != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
pinfo = sigar->pinfo;
|
|
|
|
|
|
|
|
argv_size = sizeof(*argvp) * pinfo->pr_argc;
|
|
|
|
|
|
|
|
(void)SIGAR_PROC_FILENAME(buffer, pid, "/as");
|
|
|
|
|
|
|
|
if ((fd = open(buffer, O_RDONLY)) < 0) {
|
|
|
|
return ESRCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv_size > sizeof(argvb)) {
|
|
|
|
argvp = malloc(argv_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((nread = pread(fd, argvp, argv_size, pinfo->pr_argv)) <= 0) {
|
|
|
|
close(fd);
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
procargs->number = 0;
|
|
|
|
procargs->size = pinfo->pr_argc;
|
|
|
|
procargs->data =
|
|
|
|
(char **)malloc(sizeof(*(procargs->data)) *
|
|
|
|
procargs->size);
|
|
|
|
|
|
|
|
arg = buffer;
|
|
|
|
|
|
|
|
for (n = 0; n < pinfo->pr_argc; n++) {
|
|
|
|
int alen;
|
|
|
|
char *arg;
|
|
|
|
|
|
|
|
if ((nread = pread(fd, buffer, sizeof(buffer), (off_t)argvp[n])) <= 0) {
|
|
|
|
close(fd);
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
alen = strlen(buffer)+1;
|
|
|
|
arg = malloc(alen);
|
|
|
|
memcpy(arg, buffer, alen);
|
|
|
|
|
|
|
|
procargs->data[procargs->number++] = arg;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argvp != argvb) {
|
|
|
|
free(argvp);
|
|
|
|
}
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid,
|
|
|
|
sigar_proc_env_t *procenv)
|
|
|
|
{
|
|
|
|
psinfo_t *pinfo;
|
|
|
|
int fd, status;
|
|
|
|
char buffer[BUFSIZ], *offsets[512];
|
|
|
|
size_t nread;
|
|
|
|
int n=0, max=sizeof(offsets)/sizeof(char *);
|
|
|
|
|
|
|
|
if ((status = sigar_proc_psinfo_get(sigar, pid)) != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
pinfo = sigar->pinfo;
|
|
|
|
|
|
|
|
(void)SIGAR_PROC_FILENAME(buffer, pid, "/as");
|
|
|
|
|
|
|
|
if ((fd = open(buffer, O_RDONLY)) < 0) {
|
|
|
|
return ESRCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((nread = pread(fd, offsets, sizeof(offsets),
|
|
|
|
pinfo->pr_envp)) <= 0)
|
|
|
|
{
|
|
|
|
close(fd);
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((n < max) && offsets[n]) {
|
|
|
|
char *val;
|
|
|
|
int klen, vlen, status;
|
|
|
|
char key[128]; /* XXX is there a max key size? */
|
|
|
|
|
|
|
|
if ((nread = pread(fd, buffer, sizeof(buffer),
|
|
|
|
(off_t)offsets[n++])) <= 0)
|
|
|
|
{
|
|
|
|
close(fd);
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
val = strchr(buffer, '=');
|
|
|
|
|
|
|
|
if (val == NULL) {
|
|
|
|
break; /*XXX*/
|
|
|
|
}
|
|
|
|
|
|
|
|
klen = val - buffer;
|
|
|
|
SIGAR_SSTRCPY(key, buffer);
|
|
|
|
key[klen] = '\0';
|
|
|
|
++val;
|
|
|
|
|
|
|
|
vlen = strlen(val);
|
|
|
|
|
|
|
|
status = procenv->env_getter(procenv->data,
|
|
|
|
key, klen, val, vlen);
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
/* not an error; just stop iterating */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_proc_fd_get(sigar_t *sigar, sigar_pid_t pid,
|
|
|
|
sigar_proc_fd_t *procfd)
|
|
|
|
{
|
|
|
|
int status =
|
|
|
|
sigar_proc_fd_count(sigar, pid, &procfd->total);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid,
|
|
|
|
sigar_proc_exe_t *procexe)
|
|
|
|
{
|
|
|
|
return SIGAR_ENOTIMPL;
|
|
|
|
}
|
|
|
|
|
2004-06-23 03:40:37 +08:00
|
|
|
int sigar_proc_modules_get(sigar_t *sigar, sigar_pid_t pid,
|
|
|
|
sigar_proc_modules_t *procmods)
|
|
|
|
{
|
|
|
|
return SIGAR_ENOTIMPL;
|
|
|
|
}
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
#include <sys/mnttab.h>
|
|
|
|
|
|
|
|
int sigar_os_fs_type_get(sigar_file_system_t *fsp)
|
|
|
|
{
|
|
|
|
char *type = fsp->sys_type_name;
|
|
|
|
|
|
|
|
switch (*type) {
|
|
|
|
case 'u':
|
|
|
|
if (strEQ(type, "ufs")) {
|
|
|
|
fsp->type = SIGAR_FSTYPE_LOCAL_DISK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
/* XXX */
|
|
|
|
}
|
|
|
|
|
|
|
|
return fsp->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_file_system_list_get(sigar_t *sigar,
|
|
|
|
sigar_file_system_list_t *fslist)
|
|
|
|
{
|
|
|
|
struct mnttab ent;
|
|
|
|
sigar_file_system_t *fsp;
|
|
|
|
FILE *fp = fopen(MNTTAB, "r");
|
|
|
|
|
|
|
|
if (!fp) {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
sigar_file_system_list_create(fslist);
|
|
|
|
|
|
|
|
while (getmntent(fp, &ent) == 0) {
|
|
|
|
SIGAR_FILE_SYSTEM_LIST_GROW(fslist);
|
|
|
|
|
|
|
|
fsp = &fslist->data[fslist->number++];
|
|
|
|
|
|
|
|
SIGAR_SSTRCPY(fsp->dir_name, ent.mnt_mountp);
|
|
|
|
SIGAR_SSTRCPY(fsp->dev_name, ent.mnt_special);
|
|
|
|
SIGAR_SSTRCPY(fsp->sys_type_name, ent.mnt_fstype);
|
|
|
|
sigar_fs_type_init(fsp);
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include <sys/statvfs.h>
|
|
|
|
|
|
|
|
#define SIGAR_FS_BLOCKS_TO_BYTES(buf, f) \
|
|
|
|
((buf.f * (buf.f_frsize / 512)) >> 1)
|
|
|
|
|
|
|
|
int sigar_file_system_usage_get(sigar_t *sigar,
|
|
|
|
const char *dirname,
|
|
|
|
sigar_file_system_usage_t *fsusage)
|
|
|
|
{
|
|
|
|
struct statvfs buf;
|
|
|
|
|
|
|
|
if (statvfs(dirname, &buf) != 0) {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
fsusage->total = SIGAR_FS_BLOCKS_TO_BYTES(buf, f_blocks);
|
|
|
|
fsusage->free = SIGAR_FS_BLOCKS_TO_BYTES(buf, f_bfree);
|
|
|
|
fsusage->avail = SIGAR_FS_BLOCKS_TO_BYTES(buf, f_bavail);
|
|
|
|
fsusage->files = buf.f_files;
|
|
|
|
fsusage->free_files = buf.f_files;
|
|
|
|
fsusage->use_percent = sigar_file_system_usage_calc_used(sigar, fsusage);
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_cpu_infos_get(sigar_t *sigar,
|
|
|
|
sigar_cpu_infos_t *cpu_infos)
|
|
|
|
{
|
|
|
|
processor_info_t stats;
|
|
|
|
unsigned int i;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
sigar_kstat_update(sigar); /* for sigar->ncpu */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* stats we care about will be the same for each
|
|
|
|
* online processor, so just grab the first.
|
|
|
|
*/
|
|
|
|
for (i=0; i<sigar->ncpu; i++) {
|
|
|
|
processorid_t id = sigar->ks.cpuid[i];
|
|
|
|
|
|
|
|
if ((status = processor_info(id, &stats)) < 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
status = SIGAR_OK;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
/* should never happen */
|
|
|
|
return ENOENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
sigar_cpu_infos_create(cpu_infos);
|
|
|
|
|
|
|
|
for (i=0; i<sigar->ncpu; i++) {
|
|
|
|
sigar_cpu_info_t *info;
|
|
|
|
|
|
|
|
SIGAR_CPU_INFOS_GROW(cpu_infos);
|
|
|
|
|
|
|
|
info = &cpu_infos->data[cpu_infos->number++];
|
|
|
|
|
2004-06-23 10:32:38 +08:00
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
SIGAR_SSTRCPY(info->model, stats.pi_processor_type);
|
2004-06-23 10:32:38 +08:00
|
|
|
|
|
|
|
if (strEQ(info->model, "i386")) {
|
|
|
|
/* XXX assuming Intel on x86 */
|
|
|
|
SIGAR_SSTRCPY(info->vendor, "Intel");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* sparc */
|
|
|
|
SIGAR_SSTRCPY(info->vendor, "Sun Microsystems");
|
|
|
|
}
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
info->mhz = stats.pi_clock;
|
|
|
|
info->cache_size = -1; /*XXX*/
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_net_route_list_get(sigar_t *sigar,
|
|
|
|
sigar_net_route_list_t *routelist)
|
|
|
|
|
|
|
|
{
|
|
|
|
return SIGAR_ENOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define kHME(v) kSTAT_uint(v, hme)
|
|
|
|
|
|
|
|
static int sigar_net_ifstat_get_hme(sigar_t *sigar, const char *name,
|
|
|
|
sigar_net_interface_stat_t *ifstat)
|
|
|
|
{
|
|
|
|
kstat_ctl_t *kc = sigar->kc;
|
|
|
|
kstat_t *ksp;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
status = sigar_get_multi_kstats(sigar, &sigar->ks.hme,
|
|
|
|
name, &ksp);
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
kstat_read(kc, ksp, NULL);
|
|
|
|
|
|
|
|
sigar_koffsets_init_hme(sigar, ksp);
|
|
|
|
|
|
|
|
ifstat->rx_packets = kHME(KSTAT_HME_RX_PACKETS);
|
|
|
|
ifstat->rx_bytes = kHME(KSTAT_HME_RX_BYTES);
|
|
|
|
ifstat->rx_errors = kHME(KSTAT_HME_RX_ERRORS);
|
|
|
|
ifstat->rx_dropped = kHME(KSTAT_HME_RX_DROPPED); /*XXX*/
|
|
|
|
ifstat->rx_overruns = kHME(KSTAT_HME_RX_OVERRUNS); /*XXX*/
|
|
|
|
ifstat->rx_frame = kHME(KSTAT_HME_RX_FRAME);
|
|
|
|
|
|
|
|
ifstat->tx_packets = kHME(KSTAT_HME_TX_PACKETS);
|
|
|
|
ifstat->tx_bytes = kHME(KSTAT_HME_TX_BYTES);
|
|
|
|
ifstat->tx_errors = kHME(KSTAT_HME_TX_ERRORS);
|
|
|
|
ifstat->tx_dropped = kHME(KSTAT_HME_TX_DROPPED); /*XXX*/
|
|
|
|
ifstat->tx_overruns = kHME(KSTAT_HME_TX_OVERRUNS); /*XXX*/
|
|
|
|
ifstat->tx_collisions = kHME(KSTAT_HME_TX_COLLISIONS);
|
|
|
|
ifstat->tx_carrier = kHME(KSTAT_HME_TX_CARRIER);
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define kDMFE(v) kSTAT_uint(v, dmfe)
|
|
|
|
|
|
|
|
static int sigar_net_ifstat_get_dmfe(sigar_t *sigar, const char *name,
|
|
|
|
sigar_net_interface_stat_t *ifstat)
|
|
|
|
{
|
|
|
|
kstat_ctl_t *kc = sigar->kc;
|
|
|
|
kstat_t *ksp;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
status = sigar_get_multi_kstats(sigar, &sigar->ks.dmfe,
|
|
|
|
name, &ksp);
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
kstat_read(kc, ksp, NULL);
|
|
|
|
|
|
|
|
sigar_koffsets_init_dmfe(sigar, ksp);
|
|
|
|
|
|
|
|
ifstat->rx_packets = kDMFE(KSTAT_DMFE_RX_PACKETS);
|
|
|
|
ifstat->rx_bytes = kDMFE(KSTAT_DMFE_RX_BYTES);
|
|
|
|
ifstat->rx_errors = kDMFE(KSTAT_DMFE_RX_ERRORS);
|
|
|
|
ifstat->rx_dropped = kDMFE(KSTAT_DMFE_RX_DROPPED); /*XXX*/
|
|
|
|
ifstat->rx_overruns = kDMFE(KSTAT_DMFE_RX_OVERRUNS); /*XXX*/
|
|
|
|
ifstat->rx_frame = kDMFE(KSTAT_DMFE_RX_FRAME);
|
|
|
|
|
|
|
|
ifstat->tx_packets = kDMFE(KSTAT_DMFE_TX_PACKETS);
|
|
|
|
ifstat->tx_bytes = kDMFE(KSTAT_DMFE_TX_BYTES);
|
|
|
|
ifstat->tx_errors = kDMFE(KSTAT_DMFE_TX_ERRORS);
|
|
|
|
ifstat->tx_dropped = kDMFE(KSTAT_DMFE_TX_DROPPED); /*XXX*/
|
|
|
|
ifstat->tx_overruns = kDMFE(KSTAT_DMFE_TX_OVERRUNS); /*XXX*/
|
|
|
|
ifstat->tx_collisions = kDMFE(KSTAT_DMFE_TX_COLLISIONS);
|
|
|
|
ifstat->tx_carrier = kDMFE(KSTAT_DMFE_TX_CARRIER);
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define kGE(v) kSTAT_uint(v, ge)
|
|
|
|
|
|
|
|
static int sigar_net_ifstat_get_ge(sigar_t *sigar, const char *name,
|
|
|
|
sigar_net_interface_stat_t *ifstat)
|
|
|
|
{
|
|
|
|
kstat_ctl_t *kc = sigar->kc;
|
|
|
|
kstat_t *ksp;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
status = sigar_get_multi_kstats(sigar, &sigar->ks.ge,
|
|
|
|
name, &ksp);
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
kstat_read(kc, ksp, NULL);
|
|
|
|
|
|
|
|
sigar_koffsets_init_ge(sigar, ksp);
|
|
|
|
|
|
|
|
ifstat->rx_packets = kGE(KSTAT_GE_RX_PACKETS);
|
|
|
|
ifstat->rx_bytes = kGE(KSTAT_GE_RX_BYTES);
|
|
|
|
ifstat->rx_errors = kGE(KSTAT_GE_RX_ERRORS);
|
|
|
|
ifstat->rx_dropped = kGE(KSTAT_GE_RX_DROPPED); /*XXX*/
|
|
|
|
ifstat->rx_overruns = kGE(KSTAT_GE_RX_OVERRUNS); /*XXX*/
|
|
|
|
ifstat->rx_frame = kGE(KSTAT_GE_RX_FRAME);
|
|
|
|
|
|
|
|
ifstat->tx_packets = kGE(KSTAT_GE_TX_PACKETS);
|
|
|
|
ifstat->tx_bytes = kGE(KSTAT_GE_TX_BYTES);
|
|
|
|
ifstat->tx_errors = kGE(KSTAT_GE_TX_ERRORS);
|
|
|
|
ifstat->tx_dropped = kGE(KSTAT_GE_TX_DROPPED); /*XXX*/
|
|
|
|
ifstat->tx_overruns = kGE(KSTAT_GE_TX_OVERRUNS); /*XXX*/
|
|
|
|
ifstat->tx_collisions = kGE(KSTAT_GE_TX_COLLISIONS);
|
|
|
|
ifstat->tx_carrier = kGE(KSTAT_GE_TX_CARRIER);
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define kERI(v) kSTAT_uint(v, eri)
|
|
|
|
|
|
|
|
static int sigar_net_ifstat_get_eri(sigar_t *sigar, const char *name,
|
|
|
|
sigar_net_interface_stat_t *ifstat)
|
|
|
|
{
|
|
|
|
kstat_ctl_t *kc = sigar->kc;
|
|
|
|
kstat_t *ksp;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
status = sigar_get_multi_kstats(sigar, &sigar->ks.eri,
|
|
|
|
name, &ksp);
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
kstat_read(kc, ksp, NULL);
|
|
|
|
|
|
|
|
sigar_koffsets_init_eri(sigar, ksp);
|
|
|
|
|
|
|
|
ifstat->rx_packets = kERI(KSTAT_ERI_RX_PACKETS);
|
|
|
|
ifstat->rx_bytes = kERI(KSTAT_ERI_RX_BYTES);
|
|
|
|
ifstat->rx_errors = kERI(KSTAT_ERI_RX_ERRORS);
|
|
|
|
ifstat->rx_dropped = kERI(KSTAT_ERI_RX_DROPPED); /*XXX*/
|
|
|
|
ifstat->rx_overruns = kERI(KSTAT_ERI_RX_OVERRUNS); /*XXX*/
|
|
|
|
ifstat->rx_frame = kERI(KSTAT_ERI_RX_FRAME);
|
|
|
|
|
|
|
|
ifstat->tx_packets = kERI(KSTAT_ERI_TX_PACKETS);
|
|
|
|
ifstat->tx_bytes = kERI(KSTAT_ERI_TX_BYTES);
|
|
|
|
ifstat->tx_errors = kERI(KSTAT_ERI_TX_ERRORS);
|
|
|
|
ifstat->tx_dropped = kERI(KSTAT_ERI_TX_DROPPED); /*XXX*/
|
|
|
|
ifstat->tx_overruns = kERI(KSTAT_ERI_TX_OVERRUNS); /*XXX*/
|
|
|
|
ifstat->tx_collisions = kERI(KSTAT_ERI_TX_COLLISIONS);
|
|
|
|
ifstat->tx_carrier = kERI(KSTAT_ERI_TX_CARRIER);
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define kLO(v) kSTAT_uint(v, lo)
|
|
|
|
|
|
|
|
#define jLO aHO
|
|
|
|
|
|
|
|
static int sigar_net_ifstat_get_lo(sigar_t *sigar, const char *name,
|
|
|
|
sigar_net_interface_stat_t *ifstat)
|
|
|
|
{
|
|
|
|
kstat_ctl_t *kc = sigar->kc;
|
|
|
|
kstat_t *ksp;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
status = sigar_get_multi_kstats(sigar, &sigar->ks.lo,
|
|
|
|
name, &ksp);
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
kstat_read(kc, ksp, NULL);
|
|
|
|
|
|
|
|
sigar_koffsets_init_lo(sigar, ksp);
|
|
|
|
|
|
|
|
ifstat->rx_packets = kLO(KSTAT_LO_RX_PACKETS);
|
|
|
|
ifstat->rx_bytes = -1;
|
|
|
|
ifstat->rx_errors = -1;
|
|
|
|
ifstat->rx_dropped = -1;
|
|
|
|
ifstat->rx_overruns = -1;
|
|
|
|
ifstat->rx_frame = -1;
|
|
|
|
|
|
|
|
ifstat->tx_packets = kLO(KSTAT_LO_TX_PACKETS);
|
|
|
|
ifstat->tx_bytes = -1;
|
|
|
|
ifstat->tx_errors = -1;
|
|
|
|
ifstat->tx_dropped = -1;
|
|
|
|
ifstat->tx_overruns = -1;
|
|
|
|
ifstat->tx_collisions = -1;
|
|
|
|
ifstat->tx_carrier = -1;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sigar_net_ifstat_get_any(sigar_t *sigar, const char *name,
|
|
|
|
sigar_net_interface_stat_t *ifstat)
|
|
|
|
{
|
|
|
|
kstat_ctl_t *kc = sigar->kc;
|
|
|
|
kstat_t *ksp;
|
|
|
|
kstat_named_t *data;
|
|
|
|
char dev[64], *ptr=dev;
|
|
|
|
int num, i;
|
|
|
|
|
|
|
|
kstat_chain_update(kc);
|
|
|
|
strncpy(dev, name, sizeof(dev)-1);
|
|
|
|
dev[sizeof(dev)-1] = '\0';
|
|
|
|
|
|
|
|
while (!sigar_isdigit(*ptr) && (*ptr != '\0')) {
|
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*ptr == '\0') {
|
|
|
|
return ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* iprb0 -> dev="iprb", num=0 */
|
|
|
|
num = atoi(ptr);
|
|
|
|
*ptr = '\0';
|
|
|
|
|
|
|
|
if (!(ksp = kstat_lookup(kc, dev, num, NULL))) {
|
|
|
|
return ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (kstat_read(kc, ksp, NULL) < 0) {
|
|
|
|
return ENOENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_ZERO(ifstat);
|
|
|
|
|
|
|
|
data = (kstat_named_t *)ksp->ks_data;
|
|
|
|
for (i=0; i<ksp->ks_ndata; i++) {
|
|
|
|
sigar_uint64_t value = data[i].value.ui32;
|
|
|
|
|
|
|
|
ptr = data[i].name;
|
|
|
|
|
|
|
|
switch (*ptr) {
|
|
|
|
case 'c':
|
|
|
|
if (strEQ(ptr, "collisions")) {
|
|
|
|
ifstat->tx_collisions = value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
if (strEQ(ptr, "drop")) {
|
|
|
|
ifstat->rx_dropped = value;
|
|
|
|
ifstat->tx_dropped = value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
if (strEQ(ptr, "ipackets")) {
|
|
|
|
ifstat->rx_packets = value;
|
|
|
|
}
|
|
|
|
else if (strEQ(ptr, "ierrors")) {
|
|
|
|
ifstat->rx_errors = value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
if (strEQ(ptr, "framing")) {
|
|
|
|
ifstat->rx_frame = value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
if (strEQ(ptr, "missed")) {
|
|
|
|
ifstat->rx_dropped = value;
|
|
|
|
ifstat->tx_dropped = value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
if (strEQ(ptr, "nocarrier")) {
|
|
|
|
ifstat->tx_carrier = value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
if (strEQ(ptr, "obytes")) {
|
|
|
|
ifstat->tx_bytes = value;
|
|
|
|
}
|
|
|
|
else if (strEQ(ptr, "oerrors")) {
|
|
|
|
ifstat->tx_errors = value;
|
|
|
|
}
|
|
|
|
else if (strEQ(ptr, "oflo")) {
|
|
|
|
ifstat->tx_overruns = value;
|
|
|
|
}
|
|
|
|
else if (strEQ(ptr, "opackets")) {
|
|
|
|
ifstat->tx_packets = value;
|
|
|
|
}
|
|
|
|
else if (strEQ(ptr, "toolong_errors")) {
|
|
|
|
ifstat->tx_overruns = value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
if (strEQ(ptr, "rbytes")) {
|
|
|
|
ifstat->rx_bytes = value;
|
|
|
|
}
|
|
|
|
else if (strEQ(ptr, "rx_overflow")) {
|
|
|
|
ifstat->rx_overruns = value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_net_interface_stat_get(sigar_t *sigar, const char *name,
|
|
|
|
sigar_net_interface_stat_t *ifstat)
|
|
|
|
{
|
|
|
|
switch (*name) {
|
|
|
|
case 'd':
|
|
|
|
if (strnEQ(name, "dmfe", 4)) {
|
|
|
|
return sigar_net_ifstat_get_dmfe(sigar, name, ifstat);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
if (strnEQ(name, "eri", 3)) {
|
|
|
|
return sigar_net_ifstat_get_eri(sigar, name, ifstat);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'g':
|
|
|
|
if (strnEQ(name, "ge", 2)) {
|
|
|
|
return sigar_net_ifstat_get_ge(sigar, name, ifstat);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
if (strnEQ(name, "hme", 3)) {
|
|
|
|
return sigar_net_ifstat_get_hme(sigar, name, ifstat);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
if (strnEQ(name, "lo", 2)) {
|
|
|
|
return sigar_net_ifstat_get_lo(sigar, name, ifstat);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return sigar_net_ifstat_get_any(sigar, name, ifstat);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_net_connection_list_get(sigar_t *sigar,
|
|
|
|
sigar_net_connection_list_t *connlist,
|
|
|
|
int flags)
|
|
|
|
{
|
|
|
|
return SIGAR_ENOTIMPL;
|
|
|
|
}
|