hyperic-sigar 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +339 -0
- data/EXCEPTIONS +104 -0
- data/README +2 -0
- data/Rakefile +87 -0
- data/bindings/SigarWrapper.pm +2934 -0
- data/bindings/ruby/examples/cpu_info.rb +16 -0
- data/bindings/ruby/examples/df.rb +32 -0
- data/bindings/ruby/examples/free.rb +19 -0
- data/bindings/ruby/examples/ifconfig.rb +67 -0
- data/bindings/ruby/examples/netstat.rb +54 -0
- data/bindings/ruby/examples/pargs.rb +18 -0
- data/bindings/ruby/examples/penv.rb +14 -0
- data/bindings/ruby/examples/route.rb +31 -0
- data/bindings/ruby/examples/who.rb +13 -0
- data/bindings/ruby/extconf.rb +110 -0
- data/bindings/ruby/rbsigar.c +628 -0
- data/include/sigar.h +901 -0
- data/include/sigar_fileinfo.h +141 -0
- data/include/sigar_format.h +65 -0
- data/include/sigar_getline.h +18 -0
- data/include/sigar_log.h +82 -0
- data/include/sigar_private.h +365 -0
- data/include/sigar_ptql.h +55 -0
- data/include/sigar_util.h +192 -0
- data/src/os/aix/aix_sigar.c +1927 -0
- data/src/os/aix/sigar_os.h +71 -0
- data/src/os/darwin/darwin_sigar.c +3450 -0
- data/src/os/darwin/sigar_os.h +82 -0
- data/src/os/hpux/dlpi.c +284 -0
- data/src/os/hpux/hpux_sigar.c +1205 -0
- data/src/os/hpux/sigar_os.h +51 -0
- data/src/os/linux/linux_sigar.c +2595 -0
- data/src/os/linux/sigar_os.h +84 -0
- data/src/os/netware/netware_sigar.c +719 -0
- data/src/os/netware/sigar_os.h +26 -0
- data/src/os/osf1/osf1_sigar.c +593 -0
- data/src/os/osf1/sigar_os.h +42 -0
- data/src/os/solaris/get_mib2.c +321 -0
- data/src/os/solaris/get_mib2.h +127 -0
- data/src/os/solaris/hmekstat.h +77 -0
- data/src/os/solaris/kstats.c +182 -0
- data/src/os/solaris/procfs.c +99 -0
- data/src/os/solaris/sigar_os.h +225 -0
- data/src/os/solaris/solaris_sigar.c +2561 -0
- data/src/os/stub/sigar_os.h +8 -0
- data/src/os/stub/stub_sigar.c +303 -0
- data/src/os/win32/peb.c +213 -0
- data/src/os/win32/sigar_os.h +623 -0
- data/src/os/win32/sigar_pdh.h +49 -0
- data/src/os/win32/win32_sigar.c +3718 -0
- data/src/sigar.c +2292 -0
- data/src/sigar_cache.c +181 -0
- data/src/sigar_fileinfo.c +792 -0
- data/src/sigar_format.c +649 -0
- data/src/sigar_getline.c +1849 -0
- data/src/sigar_ptql.c +1966 -0
- data/src/sigar_signal.c +218 -0
- data/src/sigar_util.c +1061 -0
- data/version.properties +11 -0
- metadata +112 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
|
3
|
+
* This file is part of SIGAR.
|
4
|
+
*
|
5
|
+
* SIGAR is free software; you can redistribute it and/or modify
|
6
|
+
* it under the terms version 2 of the GNU General Public License as
|
7
|
+
* published by the Free Software Foundation. This program is distributed
|
8
|
+
* in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
9
|
+
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
10
|
+
* PARTICULAR PURPOSE. See the GNU General Public License for more
|
11
|
+
* details.
|
12
|
+
*
|
13
|
+
* You should have received a copy of the GNU General Public License
|
14
|
+
* along with this program; if not, write to the Free Software
|
15
|
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
16
|
+
* USA.
|
17
|
+
*/
|
18
|
+
|
19
|
+
#ifndef SIGAR_OS_H
|
20
|
+
#define SIGAR_OS_H
|
21
|
+
|
22
|
+
#include <fcntl.h>
|
23
|
+
#include <errno.h>
|
24
|
+
#include <dlfcn.h>
|
25
|
+
#include <procinfo.h>
|
26
|
+
#include <sys/resource.h>
|
27
|
+
|
28
|
+
enum {
|
29
|
+
KOFFSET_LOADAVG,
|
30
|
+
KOFFSET_VAR,
|
31
|
+
KOFFSET_SYSINFO,
|
32
|
+
KOFFSET_IFNET,
|
33
|
+
KOFFSET_VMINFO,
|
34
|
+
KOFFSET_CPUINFO,
|
35
|
+
KOFFSET_TCB,
|
36
|
+
KOFFSET_MAX
|
37
|
+
};
|
38
|
+
|
39
|
+
typedef struct {
|
40
|
+
time_t mtime;
|
41
|
+
int num;
|
42
|
+
char **devs;
|
43
|
+
} swaps_t;
|
44
|
+
|
45
|
+
typedef int (*proc_fd_func_t) (sigar_t *, sigar_pid_t, sigar_proc_fd_t *);
|
46
|
+
|
47
|
+
struct sigar_t {
|
48
|
+
SIGAR_T_BASE;
|
49
|
+
int kmem;
|
50
|
+
/* offsets for seeking on kmem */
|
51
|
+
long koffsets[KOFFSET_MAX];
|
52
|
+
proc_fd_func_t getprocfd;
|
53
|
+
int pagesize;
|
54
|
+
swaps_t swaps;
|
55
|
+
time_t last_getprocs;
|
56
|
+
sigar_pid_t last_pid;
|
57
|
+
struct procsinfo64 *pinfo;
|
58
|
+
struct cpuinfo *cpuinfo;
|
59
|
+
int cpuinfo_size;
|
60
|
+
int cpu_mhz;
|
61
|
+
char model[128];
|
62
|
+
int aix_version;
|
63
|
+
int thrusage;
|
64
|
+
sigar_cache_t *diskmap;
|
65
|
+
};
|
66
|
+
|
67
|
+
#define HAVE_STRERROR_R
|
68
|
+
|
69
|
+
#define SIGAR_EPERM_KMEM (SIGAR_OS_START_ERROR+EACCES)
|
70
|
+
|
71
|
+
#endif /* SIGAR_OS_H */
|
@@ -0,0 +1,3450 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
|
3
|
+
* This file is part of SIGAR.
|
4
|
+
*
|
5
|
+
* SIGAR is free software; you can redistribute it and/or modify
|
6
|
+
* it under the terms version 2 of the GNU General Public License as
|
7
|
+
* published by the Free Software Foundation. This program is distributed
|
8
|
+
* in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
9
|
+
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
10
|
+
* PARTICULAR PURPOSE. See the GNU General Public License for more
|
11
|
+
* details.
|
12
|
+
*
|
13
|
+
* You should have received a copy of the GNU General Public License
|
14
|
+
* along with this program; if not, write to the Free Software
|
15
|
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
16
|
+
* USA.
|
17
|
+
*/
|
18
|
+
|
19
|
+
#include "sigar.h"
|
20
|
+
#include "sigar_private.h"
|
21
|
+
#include "sigar_util.h"
|
22
|
+
#include "sigar_os.h"
|
23
|
+
|
24
|
+
#include <sys/param.h>
|
25
|
+
#include <sys/mount.h>
|
26
|
+
#include <nfs/rpcv2.h>
|
27
|
+
#include <nfs/nfsproto.h>
|
28
|
+
|
29
|
+
#ifdef DARWIN
|
30
|
+
#include <dlfcn.h>
|
31
|
+
#include <mach/mach_init.h>
|
32
|
+
#include <mach/message.h>
|
33
|
+
#include <mach/kern_return.h>
|
34
|
+
#include <mach/mach_host.h>
|
35
|
+
#include <mach/mach_traps.h>
|
36
|
+
#include <mach/mach_port.h>
|
37
|
+
#include <mach/task.h>
|
38
|
+
#include <mach/thread_act.h>
|
39
|
+
#include <mach/thread_info.h>
|
40
|
+
#include <mach/vm_map.h>
|
41
|
+
#include <mach/shared_memory_server.h>
|
42
|
+
#include <mach-o/dyld.h>
|
43
|
+
#define __OPENTRANSPORTPROVIDERS__
|
44
|
+
#include <Gestalt.h>
|
45
|
+
#include <CFString.h>
|
46
|
+
#include <CoreFoundation/CoreFoundation.h>
|
47
|
+
#include <IOKit/IOBSD.h>
|
48
|
+
#include <IOKit/IOKitLib.h>
|
49
|
+
#include <IOKit/IOTypes.h>
|
50
|
+
#include <IOKit/storage/IOBlockStorageDriver.h>
|
51
|
+
#else
|
52
|
+
#include <sys/dkstat.h>
|
53
|
+
#include <sys/types.h>
|
54
|
+
#include <sys/param.h>
|
55
|
+
#include <sys/user.h>
|
56
|
+
#include <sys/vmmeter.h>
|
57
|
+
#include <fcntl.h>
|
58
|
+
#include <stdio.h>
|
59
|
+
#endif
|
60
|
+
|
61
|
+
#if defined(__FreeBSD__) && (__FreeBSD_version >= 500013)
|
62
|
+
#define SIGAR_FREEBSD5_NFSSTAT
|
63
|
+
#include <nfsclient/nfs.h>
|
64
|
+
#include <nfsserver/nfs.h>
|
65
|
+
#else
|
66
|
+
#include <nfs/nfs.h>
|
67
|
+
#endif
|
68
|
+
|
69
|
+
#include <sys/ioctl.h>
|
70
|
+
#include <sys/mount.h>
|
71
|
+
#include <sys/resource.h>
|
72
|
+
#include <sys/stat.h>
|
73
|
+
#include <sys/socket.h>
|
74
|
+
#include <sys/sockio.h>
|
75
|
+
|
76
|
+
#include <net/if.h>
|
77
|
+
#include <net/if_dl.h>
|
78
|
+
#include <net/if_types.h>
|
79
|
+
#include <net/route.h>
|
80
|
+
#include <netinet/in.h>
|
81
|
+
|
82
|
+
#include <dirent.h>
|
83
|
+
#include <errno.h>
|
84
|
+
|
85
|
+
#include <sys/socketvar.h>
|
86
|
+
#include <netinet/in.h>
|
87
|
+
#include <netinet/in_systm.h>
|
88
|
+
#include <netinet/ip.h>
|
89
|
+
#include <netinet/in_pcb.h>
|
90
|
+
#include <netinet/tcp.h>
|
91
|
+
#include <netinet/tcp_timer.h>
|
92
|
+
#ifdef __NetBSD__
|
93
|
+
#include <netinet/ip_var.h>
|
94
|
+
#include <sys/lwp.h>
|
95
|
+
#include <sys/mount.h>
|
96
|
+
#define SRUN LSRUN
|
97
|
+
#define SSLEEP LSSLEEP
|
98
|
+
#define SDEAD LSDEAD
|
99
|
+
#define SONPROC LSONPROC
|
100
|
+
#define SSUSPENDED LSSUSPENDED
|
101
|
+
#include <sys/sched.h>
|
102
|
+
#endif
|
103
|
+
#include <netinet/tcp_var.h>
|
104
|
+
#include <netinet/tcp_fsm.h>
|
105
|
+
|
106
|
+
#define NMIB(mib) (sizeof(mib)/sizeof(mib[0]))
|
107
|
+
|
108
|
+
#ifdef __FreeBSD__
|
109
|
+
# if (__FreeBSD_version >= 500013)
|
110
|
+
# define SIGAR_FREEBSD5
|
111
|
+
# else
|
112
|
+
# define SIGAR_FREEBSD4
|
113
|
+
# endif
|
114
|
+
#endif
|
115
|
+
|
116
|
+
#if defined(SIGAR_FREEBSD5)
|
117
|
+
|
118
|
+
#define KI_FD ki_fd
|
119
|
+
#define KI_PID ki_pid
|
120
|
+
#define KI_PPID ki_ppid
|
121
|
+
#define KI_PRI ki_pri.pri_user
|
122
|
+
#define KI_NICE ki_nice
|
123
|
+
#define KI_COMM ki_comm
|
124
|
+
#define KI_STAT ki_stat
|
125
|
+
#define KI_UID ki_ruid
|
126
|
+
#define KI_GID ki_rgid
|
127
|
+
#define KI_EUID ki_svuid
|
128
|
+
#define KI_EGID ki_svgid
|
129
|
+
#define KI_SIZE ki_size
|
130
|
+
#define KI_RSS ki_rssize
|
131
|
+
#define KI_TSZ ki_tsize
|
132
|
+
#define KI_DSZ ki_dsize
|
133
|
+
#define KI_SSZ ki_ssize
|
134
|
+
#define KI_FLAG ki_flag
|
135
|
+
#define KI_START ki_start
|
136
|
+
|
137
|
+
#elif defined(DARWIN) || defined(SIGAR_FREEBSD4) || defined(__OpenBSD__) || defined(__NetBSD__)
|
138
|
+
|
139
|
+
#define KI_FD kp_proc.p_fd
|
140
|
+
#define KI_PID kp_proc.p_pid
|
141
|
+
#define KI_PPID kp_eproc.e_ppid
|
142
|
+
#define KI_PRI kp_proc.p_priority
|
143
|
+
#define KI_NICE kp_proc.p_nice
|
144
|
+
#define KI_COMM kp_proc.p_comm
|
145
|
+
#define KI_STAT kp_proc.p_stat
|
146
|
+
#define KI_UID kp_eproc.e_pcred.p_ruid
|
147
|
+
#define KI_GID kp_eproc.e_pcred.p_rgid
|
148
|
+
#define KI_EUID kp_eproc.e_pcred.p_svuid
|
149
|
+
#define KI_EGID kp_eproc.e_pcred.p_svgid
|
150
|
+
#define KI_SIZE XXX
|
151
|
+
#define KI_RSS kp_eproc.e_vm.vm_rssize
|
152
|
+
#define KI_TSZ kp_eproc.e_vm.vm_tsize
|
153
|
+
#define KI_DSZ kp_eproc.e_vm.vm_dsize
|
154
|
+
#define KI_SSZ kp_eproc.e_vm.vm_ssize
|
155
|
+
#define KI_FLAG kp_eproc.e_flag
|
156
|
+
#define KI_START kp_proc.p_starttime
|
157
|
+
|
158
|
+
#endif
|
159
|
+
|
160
|
+
#ifndef DARWIN
|
161
|
+
|
162
|
+
#define PROCFS_STATUS(status) \
|
163
|
+
((((status) != SIGAR_OK) && !sigar->proc_mounted) ? \
|
164
|
+
SIGAR_ENOTIMPL : status)
|
165
|
+
|
166
|
+
static int get_koffsets(sigar_t *sigar)
|
167
|
+
{
|
168
|
+
int i;
|
169
|
+
struct nlist klist[] = {
|
170
|
+
{ "_cp_time" },
|
171
|
+
{ "_cnt" },
|
172
|
+
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
173
|
+
{ "_tcpstat" },
|
174
|
+
{ "_tcbtable" },
|
175
|
+
#endif
|
176
|
+
{ NULL }
|
177
|
+
};
|
178
|
+
|
179
|
+
if (!sigar->kmem) {
|
180
|
+
return SIGAR_EPERM_KMEM;
|
181
|
+
}
|
182
|
+
|
183
|
+
kvm_nlist(sigar->kmem, klist);
|
184
|
+
|
185
|
+
for (i=0; i<KOFFSET_MAX; i++) {
|
186
|
+
sigar->koffsets[i] = klist[i].n_value;
|
187
|
+
}
|
188
|
+
|
189
|
+
return SIGAR_OK;
|
190
|
+
}
|
191
|
+
|
192
|
+
static int kread(sigar_t *sigar, void *data, int size, long offset)
|
193
|
+
{
|
194
|
+
if (!sigar->kmem) {
|
195
|
+
return SIGAR_EPERM_KMEM;
|
196
|
+
}
|
197
|
+
|
198
|
+
if (kvm_read(sigar->kmem, offset, data, size) != size) {
|
199
|
+
return errno;
|
200
|
+
}
|
201
|
+
|
202
|
+
return SIGAR_OK;
|
203
|
+
}
|
204
|
+
#endif
|
205
|
+
|
206
|
+
int sigar_os_open(sigar_t **sigar)
|
207
|
+
{
|
208
|
+
int mib[2];
|
209
|
+
int ncpu;
|
210
|
+
size_t len;
|
211
|
+
struct timeval boottime;
|
212
|
+
#ifndef DARWIN
|
213
|
+
struct stat sb;
|
214
|
+
#endif
|
215
|
+
|
216
|
+
len = sizeof(ncpu);
|
217
|
+
mib[0] = CTL_HW;
|
218
|
+
mib[1] = HW_NCPU;
|
219
|
+
if (sysctl(mib, NMIB(mib), &ncpu, &len, NULL, 0) < 0) {
|
220
|
+
return errno;
|
221
|
+
}
|
222
|
+
|
223
|
+
len = sizeof(boottime);
|
224
|
+
mib[0] = CTL_KERN;
|
225
|
+
mib[1] = KERN_BOOTTIME;
|
226
|
+
if (sysctl(mib, NMIB(mib), &boottime, &len, NULL, 0) < 0) {
|
227
|
+
return errno;
|
228
|
+
}
|
229
|
+
|
230
|
+
*sigar = malloc(sizeof(**sigar));
|
231
|
+
|
232
|
+
#ifdef DARWIN
|
233
|
+
(*sigar)->mach_port = mach_host_self();
|
234
|
+
# ifdef DARWIN_HAS_LIBPROC_H
|
235
|
+
if (((*sigar)->libproc = dlopen("/usr/lib/libproc.dylib", 0))) {
|
236
|
+
(*sigar)->proc_pidinfo = dlsym((*sigar)->libproc, "proc_pidinfo");
|
237
|
+
(*sigar)->proc_pidfdinfo = dlsym((*sigar)->libproc, "proc_pidfdinfo");
|
238
|
+
}
|
239
|
+
# endif
|
240
|
+
#else
|
241
|
+
(*sigar)->kmem = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
|
242
|
+
if (stat("/proc/curproc", &sb) < 0) {
|
243
|
+
(*sigar)->proc_mounted = 0;
|
244
|
+
}
|
245
|
+
else {
|
246
|
+
(*sigar)->proc_mounted = 1;
|
247
|
+
}
|
248
|
+
#endif
|
249
|
+
|
250
|
+
#ifndef DARWIN
|
251
|
+
get_koffsets(*sigar);
|
252
|
+
#endif
|
253
|
+
|
254
|
+
(*sigar)->ncpu = ncpu;
|
255
|
+
(*sigar)->lcpu = -1;
|
256
|
+
(*sigar)->argmax = 0;
|
257
|
+
(*sigar)->boot_time = boottime.tv_sec; /* XXX seems off a bit */
|
258
|
+
|
259
|
+
(*sigar)->pagesize = getpagesize();
|
260
|
+
#ifdef __FreeBSD__
|
261
|
+
(*sigar)->ticks = 100; /* sysconf(_SC_CLK_TCK) == 128 !? */
|
262
|
+
#else
|
263
|
+
(*sigar)->ticks = sysconf(_SC_CLK_TCK);
|
264
|
+
#endif
|
265
|
+
(*sigar)->last_pid = -1;
|
266
|
+
|
267
|
+
(*sigar)->pinfo = NULL;
|
268
|
+
|
269
|
+
return SIGAR_OK;
|
270
|
+
}
|
271
|
+
|
272
|
+
int sigar_os_close(sigar_t *sigar)
|
273
|
+
{
|
274
|
+
if (sigar->pinfo) {
|
275
|
+
free(sigar->pinfo);
|
276
|
+
}
|
277
|
+
#ifndef DARWIN
|
278
|
+
if (sigar->kmem) {
|
279
|
+
kvm_close(sigar->kmem);
|
280
|
+
}
|
281
|
+
#endif
|
282
|
+
free(sigar);
|
283
|
+
return SIGAR_OK;
|
284
|
+
}
|
285
|
+
|
286
|
+
char *sigar_os_error_string(sigar_t *sigar, int err)
|
287
|
+
{
|
288
|
+
switch (err) {
|
289
|
+
case SIGAR_EPERM_KMEM:
|
290
|
+
return "Failed to open /dev/kmem for reading";
|
291
|
+
case SIGAR_EPROC_NOENT:
|
292
|
+
return "/proc filesystem is not mounted";
|
293
|
+
default:
|
294
|
+
return NULL;
|
295
|
+
}
|
296
|
+
}
|
297
|
+
|
298
|
+
/* ARG_MAX in FreeBSD 6.0 == 262144, which blows up the stack */
|
299
|
+
#define SIGAR_ARG_MAX 65536
|
300
|
+
|
301
|
+
#ifdef DARWIN
|
302
|
+
static size_t sigar_argmax_get(sigar_t *sigar)
|
303
|
+
{
|
304
|
+
#ifdef KERN_ARGMAX
|
305
|
+
int mib[] = { CTL_KERN, KERN_ARGMAX };
|
306
|
+
size_t size = sizeof(sigar->argmax);
|
307
|
+
|
308
|
+
if (sigar->argmax != 0) {
|
309
|
+
return sigar->argmax;
|
310
|
+
}
|
311
|
+
if (sysctl(mib, NMIB(mib), &sigar->argmax, &size, NULL, 0) == 0) {
|
312
|
+
return sigar->argmax;
|
313
|
+
}
|
314
|
+
#endif
|
315
|
+
return SIGAR_ARG_MAX;
|
316
|
+
}
|
317
|
+
#endif /* DARWIN */
|
318
|
+
|
319
|
+
#if defined(DARWIN)
|
320
|
+
static int sigar_vmstat(sigar_t *sigar, vm_statistics_data_t *vmstat)
|
321
|
+
{
|
322
|
+
kern_return_t status;
|
323
|
+
mach_msg_type_number_t count = sizeof(*vmstat) / sizeof(integer_t);
|
324
|
+
|
325
|
+
status = host_statistics(sigar->mach_port, HOST_VM_INFO,
|
326
|
+
(host_info_t)vmstat, &count);
|
327
|
+
|
328
|
+
if (status == KERN_SUCCESS) {
|
329
|
+
return SIGAR_OK;
|
330
|
+
}
|
331
|
+
else {
|
332
|
+
return errno;
|
333
|
+
}
|
334
|
+
}
|
335
|
+
#elif defined(__FreeBSD__)
|
336
|
+
static int sigar_vmstat(sigar_t *sigar, struct vmmeter *vmstat)
|
337
|
+
{
|
338
|
+
int status;
|
339
|
+
size_t size = sizeof(unsigned int);
|
340
|
+
|
341
|
+
status = kread(sigar, vmstat, sizeof(*vmstat),
|
342
|
+
sigar->koffsets[KOFFSET_VMMETER]);
|
343
|
+
|
344
|
+
if (status == SIGAR_OK) {
|
345
|
+
return SIGAR_OK;
|
346
|
+
}
|
347
|
+
|
348
|
+
SIGAR_ZERO(vmstat);
|
349
|
+
|
350
|
+
/* derived from src/usr.bin/vmstat/vmstat.c */
|
351
|
+
/* only collect the ones we actually use */
|
352
|
+
#define GET_VM_STATS(cat, name, used) \
|
353
|
+
if (used) sysctlbyname("vm.stats." #cat "." #name, &vmstat->name, &size, NULL, 0)
|
354
|
+
|
355
|
+
/* sys */
|
356
|
+
GET_VM_STATS(sys, v_swtch, 0);
|
357
|
+
GET_VM_STATS(sys, v_trap, 0);
|
358
|
+
GET_VM_STATS(sys, v_syscall, 0);
|
359
|
+
GET_VM_STATS(sys, v_intr, 0);
|
360
|
+
GET_VM_STATS(sys, v_soft, 0);
|
361
|
+
|
362
|
+
/* vm */
|
363
|
+
GET_VM_STATS(vm, v_vm_faults, 0);
|
364
|
+
GET_VM_STATS(vm, v_cow_faults, 0);
|
365
|
+
GET_VM_STATS(vm, v_cow_optim, 0);
|
366
|
+
GET_VM_STATS(vm, v_zfod, 0);
|
367
|
+
GET_VM_STATS(vm, v_ozfod, 0);
|
368
|
+
GET_VM_STATS(vm, v_swapin, 1);
|
369
|
+
GET_VM_STATS(vm, v_swapout, 1);
|
370
|
+
GET_VM_STATS(vm, v_swappgsin, 0);
|
371
|
+
GET_VM_STATS(vm, v_swappgsout, 0);
|
372
|
+
GET_VM_STATS(vm, v_vnodein, 1);
|
373
|
+
GET_VM_STATS(vm, v_vnodeout, 1);
|
374
|
+
GET_VM_STATS(vm, v_vnodepgsin, 0);
|
375
|
+
GET_VM_STATS(vm, v_vnodepgsout, 0);
|
376
|
+
GET_VM_STATS(vm, v_intrans, 0);
|
377
|
+
GET_VM_STATS(vm, v_reactivated, 0);
|
378
|
+
GET_VM_STATS(vm, v_pdwakeups, 0);
|
379
|
+
GET_VM_STATS(vm, v_pdpages, 0);
|
380
|
+
GET_VM_STATS(vm, v_dfree, 0);
|
381
|
+
GET_VM_STATS(vm, v_pfree, 0);
|
382
|
+
GET_VM_STATS(vm, v_tfree, 0);
|
383
|
+
GET_VM_STATS(vm, v_page_size, 0);
|
384
|
+
GET_VM_STATS(vm, v_page_count, 0);
|
385
|
+
GET_VM_STATS(vm, v_free_reserved, 0);
|
386
|
+
GET_VM_STATS(vm, v_free_target, 0);
|
387
|
+
GET_VM_STATS(vm, v_free_min, 0);
|
388
|
+
GET_VM_STATS(vm, v_free_count, 1);
|
389
|
+
GET_VM_STATS(vm, v_wire_count, 0);
|
390
|
+
GET_VM_STATS(vm, v_active_count, 0);
|
391
|
+
GET_VM_STATS(vm, v_inactive_target, 0);
|
392
|
+
GET_VM_STATS(vm, v_inactive_count, 0);
|
393
|
+
GET_VM_STATS(vm, v_cache_count, 0);
|
394
|
+
GET_VM_STATS(vm, v_cache_min, 0);
|
395
|
+
GET_VM_STATS(vm, v_cache_max, 0);
|
396
|
+
GET_VM_STATS(vm, v_pageout_free_min, 0);
|
397
|
+
GET_VM_STATS(vm, v_interrupt_free_min, 0);
|
398
|
+
GET_VM_STATS(vm, v_forks, 0);
|
399
|
+
GET_VM_STATS(vm, v_vforks, 0);
|
400
|
+
GET_VM_STATS(vm, v_rforks, 0);
|
401
|
+
GET_VM_STATS(vm, v_kthreads, 0);
|
402
|
+
GET_VM_STATS(vm, v_forkpages, 0);
|
403
|
+
GET_VM_STATS(vm, v_vforkpages, 0);
|
404
|
+
GET_VM_STATS(vm, v_rforkpages, 0);
|
405
|
+
GET_VM_STATS(vm, v_kthreadpages, 0);
|
406
|
+
#undef GET_VM_STATS
|
407
|
+
|
408
|
+
return SIGAR_OK;
|
409
|
+
}
|
410
|
+
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
411
|
+
static int sigar_vmstat(sigar_t *sigar, struct uvmexp *vmstat)
|
412
|
+
{
|
413
|
+
size_t size = sizeof(*vmstat);
|
414
|
+
int mib[] = { CTL_VM, VM_UVMEXP };
|
415
|
+
if (sysctl(mib, NMIB(mib), vmstat, &size, NULL, 0) < 0) {
|
416
|
+
return errno;
|
417
|
+
}
|
418
|
+
else {
|
419
|
+
return SIGAR_OK;
|
420
|
+
}
|
421
|
+
}
|
422
|
+
#endif
|
423
|
+
|
424
|
+
int sigar_mem_get(sigar_t *sigar, sigar_mem_t *mem)
|
425
|
+
{
|
426
|
+
#ifdef DARWIN
|
427
|
+
vm_statistics_data_t vmstat;
|
428
|
+
uint64_t mem_total;
|
429
|
+
#else
|
430
|
+
unsigned long mem_total;
|
431
|
+
#endif
|
432
|
+
#if defined(__FreeBSD__)
|
433
|
+
struct vmmeter vmstat;
|
434
|
+
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
435
|
+
struct uvmexp vmstat;
|
436
|
+
#endif
|
437
|
+
int mib[2];
|
438
|
+
size_t len;
|
439
|
+
int status;
|
440
|
+
|
441
|
+
mib[0] = CTL_HW;
|
442
|
+
|
443
|
+
mib[1] = HW_PAGESIZE;
|
444
|
+
len = sizeof(sigar->pagesize);
|
445
|
+
if (sysctl(mib, NMIB(mib), &sigar->pagesize, &len, NULL, 0) < 0) {
|
446
|
+
return errno;
|
447
|
+
}
|
448
|
+
|
449
|
+
#ifdef DARWIN
|
450
|
+
mib[1] = HW_MEMSIZE;
|
451
|
+
#else
|
452
|
+
mib[1] = HW_PHYSMEM;
|
453
|
+
#endif
|
454
|
+
len = sizeof(mem_total);
|
455
|
+
if (sysctl(mib, NMIB(mib), &mem_total, &len, NULL, 0) < 0) {
|
456
|
+
return errno;
|
457
|
+
}
|
458
|
+
|
459
|
+
mem->total = mem_total;
|
460
|
+
|
461
|
+
#if defined(DARWIN)
|
462
|
+
if ((status = sigar_vmstat(sigar, &vmstat)) != SIGAR_OK) {
|
463
|
+
return status;
|
464
|
+
}
|
465
|
+
|
466
|
+
mem->free = vmstat.free_count;
|
467
|
+
mem->free *= sigar->pagesize;
|
468
|
+
#elif defined(__FreeBSD__)
|
469
|
+
if ((status = sigar_vmstat(sigar, &vmstat)) == SIGAR_OK) {
|
470
|
+
mem->free = vmstat.v_free_count;
|
471
|
+
mem->free *= sigar->pagesize;
|
472
|
+
}
|
473
|
+
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
474
|
+
if ((status = sigar_vmstat(sigar, &vmstat)) != SIGAR_OK) {
|
475
|
+
return status;
|
476
|
+
}
|
477
|
+
mem->free = vmstat.free;
|
478
|
+
#endif
|
479
|
+
|
480
|
+
mem->used = mem->total - mem->free;
|
481
|
+
|
482
|
+
mem->actual_free = mem->free;
|
483
|
+
mem->actual_used = mem->used;
|
484
|
+
|
485
|
+
sigar_mem_calc_ram(sigar, mem);
|
486
|
+
|
487
|
+
return SIGAR_OK;
|
488
|
+
}
|
489
|
+
|
490
|
+
#define SWI_MAXMIB 3
|
491
|
+
|
492
|
+
#ifdef SIGAR_FREEBSD5
|
493
|
+
/* code in this function is based on FreeBSD 5.3 kvm_getswapinfo.c */
|
494
|
+
static int getswapinfo_sysctl(struct kvm_swap *swap_ary,
|
495
|
+
int swap_max)
|
496
|
+
{
|
497
|
+
int ti, ttl;
|
498
|
+
size_t mibi, len, size;
|
499
|
+
int soid[SWI_MAXMIB];
|
500
|
+
struct xswdev xsd;
|
501
|
+
struct kvm_swap tot;
|
502
|
+
int unswdev, dmmax;
|
503
|
+
|
504
|
+
/* XXX this can be optimized by using os_open */
|
505
|
+
size = sizeof(dmmax);
|
506
|
+
if (sysctlbyname("vm.dmmax", &dmmax, &size, NULL, 0) == -1) {
|
507
|
+
return errno;
|
508
|
+
}
|
509
|
+
|
510
|
+
mibi = SWI_MAXMIB - 1;
|
511
|
+
if (sysctlnametomib("vm.swap_info", soid, &mibi) == -1) {
|
512
|
+
return errno;
|
513
|
+
}
|
514
|
+
|
515
|
+
bzero(&tot, sizeof(tot));
|
516
|
+
for (unswdev = 0;; unswdev++) {
|
517
|
+
soid[mibi] = unswdev;
|
518
|
+
len = sizeof(xsd);
|
519
|
+
if (sysctl(soid, mibi + 1, &xsd, &len, NULL, 0) == -1) {
|
520
|
+
if (errno == ENOENT) {
|
521
|
+
break;
|
522
|
+
}
|
523
|
+
return errno;
|
524
|
+
}
|
525
|
+
#if 0
|
526
|
+
if (len != sizeof(xsd)) {
|
527
|
+
_kvm_err(kd, kd->program, "struct xswdev has unexpected "
|
528
|
+
"size; kernel and libkvm out of sync?");
|
529
|
+
return -1;
|
530
|
+
}
|
531
|
+
if (xsd.xsw_version != XSWDEV_VERSION) {
|
532
|
+
_kvm_err(kd, kd->program, "struct xswdev version "
|
533
|
+
"mismatch; kernel and libkvm out of sync?");
|
534
|
+
return -1;
|
535
|
+
}
|
536
|
+
#endif
|
537
|
+
ttl = xsd.xsw_nblks - dmmax;
|
538
|
+
if (unswdev < swap_max - 1) {
|
539
|
+
bzero(&swap_ary[unswdev], sizeof(swap_ary[unswdev]));
|
540
|
+
swap_ary[unswdev].ksw_total = ttl;
|
541
|
+
swap_ary[unswdev].ksw_used = xsd.xsw_used;
|
542
|
+
swap_ary[unswdev].ksw_flags = xsd.xsw_flags;
|
543
|
+
}
|
544
|
+
tot.ksw_total += ttl;
|
545
|
+
tot.ksw_used += xsd.xsw_used;
|
546
|
+
}
|
547
|
+
|
548
|
+
ti = unswdev;
|
549
|
+
if (ti >= swap_max) {
|
550
|
+
ti = swap_max - 1;
|
551
|
+
}
|
552
|
+
if (ti >= 0) {
|
553
|
+
swap_ary[ti] = tot;
|
554
|
+
}
|
555
|
+
|
556
|
+
return SIGAR_OK;
|
557
|
+
}
|
558
|
+
#else
|
559
|
+
#define getswapinfo_sysctl(swap_ary, swap_max) SIGAR_ENOTIMPL
|
560
|
+
#endif
|
561
|
+
|
562
|
+
#define SIGAR_FS_BLOCKS_TO_BYTES(val, bsize) ((val * bsize) >> 1)
|
563
|
+
|
564
|
+
#ifdef DARWIN
|
565
|
+
#define VM_DIR "/private/var/vm"
|
566
|
+
#define SWAPFILE "swapfile"
|
567
|
+
|
568
|
+
static int sigar_swap_fs_get(sigar_t *sigar, sigar_swap_t *swap) /* <= 10.3 */
|
569
|
+
{
|
570
|
+
DIR *dirp;
|
571
|
+
struct dirent *ent;
|
572
|
+
char swapfile[SSTRLEN(VM_DIR) + SSTRLEN("/") + SSTRLEN(SWAPFILE) + 12];
|
573
|
+
struct stat swapstat;
|
574
|
+
struct statfs vmfs;
|
575
|
+
sigar_uint64_t val, bsize;
|
576
|
+
|
577
|
+
swap->used = swap->total = swap->free = 0;
|
578
|
+
|
579
|
+
if (!(dirp = opendir(VM_DIR))) {
|
580
|
+
return errno;
|
581
|
+
}
|
582
|
+
|
583
|
+
/* looking for "swapfile0", "swapfile1", etc. */
|
584
|
+
while ((ent = readdir(dirp))) {
|
585
|
+
char *ptr = swapfile;
|
586
|
+
|
587
|
+
if ((ent->d_namlen < SSTRLEN(SWAPFILE)+1) || /* n/a, see comment above */
|
588
|
+
(ent->d_namlen > SSTRLEN(SWAPFILE)+11)) /* ensure no overflow */
|
589
|
+
{
|
590
|
+
continue;
|
591
|
+
}
|
592
|
+
|
593
|
+
if (!strnEQ(ent->d_name, SWAPFILE, SSTRLEN(SWAPFILE))) {
|
594
|
+
continue;
|
595
|
+
}
|
596
|
+
|
597
|
+
/* sprintf(swapfile, "%s/%s", VM_DIR, ent->d_name) */
|
598
|
+
|
599
|
+
memcpy(ptr, VM_DIR, SSTRLEN(VM_DIR));
|
600
|
+
ptr += SSTRLEN(VM_DIR);
|
601
|
+
|
602
|
+
*ptr++ = '/';
|
603
|
+
|
604
|
+
memcpy(ptr, ent->d_name, ent->d_namlen+1);
|
605
|
+
|
606
|
+
if (stat(swapfile, &swapstat) < 0) {
|
607
|
+
continue;
|
608
|
+
}
|
609
|
+
|
610
|
+
swap->used += swapstat.st_size;
|
611
|
+
}
|
612
|
+
|
613
|
+
closedir(dirp);
|
614
|
+
|
615
|
+
if (statfs(VM_DIR, &vmfs) < 0) {
|
616
|
+
return errno;
|
617
|
+
}
|
618
|
+
|
619
|
+
bsize = vmfs.f_bsize / 512;
|
620
|
+
val = vmfs.f_bfree;
|
621
|
+
swap->total = SIGAR_FS_BLOCKS_TO_BYTES(val, bsize) + swap->used;
|
622
|
+
|
623
|
+
swap->free = swap->total - swap->used;
|
624
|
+
|
625
|
+
return SIGAR_OK;
|
626
|
+
}
|
627
|
+
|
628
|
+
static int sigar_swap_sysctl_get(sigar_t *sigar, sigar_swap_t *swap)
|
629
|
+
|
630
|
+
{
|
631
|
+
#ifdef VM_SWAPUSAGE /* => 10.4 */
|
632
|
+
struct xsw_usage sw_usage;
|
633
|
+
size_t size = sizeof(sw_usage);
|
634
|
+
int mib[] = { CTL_VM, VM_SWAPUSAGE };
|
635
|
+
|
636
|
+
if (sysctl(mib, NMIB(mib), &sw_usage, &size, NULL, 0) != 0) {
|
637
|
+
return errno;
|
638
|
+
}
|
639
|
+
|
640
|
+
swap->total = sw_usage.xsu_total;
|
641
|
+
swap->used = sw_usage.xsu_used;
|
642
|
+
swap->free = sw_usage.xsu_avail;
|
643
|
+
|
644
|
+
return SIGAR_OK;
|
645
|
+
#else
|
646
|
+
return SIGAR_ENOTIMPL; /* <= 10.3 */
|
647
|
+
#endif
|
648
|
+
}
|
649
|
+
#endif /* DARWIN */
|
650
|
+
|
651
|
+
int sigar_swap_get(sigar_t *sigar, sigar_swap_t *swap)
|
652
|
+
{
|
653
|
+
int status;
|
654
|
+
#if defined(DARWIN)
|
655
|
+
vm_statistics_data_t vmstat;
|
656
|
+
|
657
|
+
if (sigar_swap_sysctl_get(sigar, swap) != SIGAR_OK) {
|
658
|
+
status = sigar_swap_fs_get(sigar, swap); /* <= 10.3 */
|
659
|
+
if (status != SIGAR_OK) {
|
660
|
+
return status;
|
661
|
+
}
|
662
|
+
}
|
663
|
+
|
664
|
+
if ((status = sigar_vmstat(sigar, &vmstat)) != SIGAR_OK) {
|
665
|
+
return status;
|
666
|
+
}
|
667
|
+
swap->page_in = vmstat.pageins;
|
668
|
+
swap->page_out = vmstat.pageouts;
|
669
|
+
#elif defined(__FreeBSD__)
|
670
|
+
struct kvm_swap kswap[1];
|
671
|
+
struct vmmeter vmstat;
|
672
|
+
|
673
|
+
if (getswapinfo_sysctl(kswap, 1) != SIGAR_OK) {
|
674
|
+
if (!sigar->kmem) {
|
675
|
+
return SIGAR_EPERM_KMEM;
|
676
|
+
}
|
677
|
+
|
678
|
+
if (kvm_getswapinfo(sigar->kmem, kswap, 1, 0) < 0) {
|
679
|
+
return errno;
|
680
|
+
}
|
681
|
+
}
|
682
|
+
|
683
|
+
if (kswap[0].ksw_total == 0) {
|
684
|
+
swap->total = 0;
|
685
|
+
swap->used = 0;
|
686
|
+
swap->free = 0;
|
687
|
+
return SIGAR_OK;
|
688
|
+
}
|
689
|
+
|
690
|
+
swap->total = kswap[0].ksw_total * sigar->pagesize;
|
691
|
+
swap->used = kswap[0].ksw_used * sigar->pagesize;
|
692
|
+
swap->free = swap->total - swap->used;
|
693
|
+
|
694
|
+
if ((status = sigar_vmstat(sigar, &vmstat)) == SIGAR_OK) {
|
695
|
+
swap->page_in = vmstat.v_swapin + vmstat.v_vnodein;
|
696
|
+
swap->page_out = vmstat.v_swapout + vmstat.v_vnodeout;
|
697
|
+
}
|
698
|
+
else {
|
699
|
+
swap->page_in = swap->page_out = -1;
|
700
|
+
}
|
701
|
+
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
702
|
+
struct uvmexp vmstat;
|
703
|
+
|
704
|
+
if ((status = sigar_vmstat(sigar, &vmstat)) != SIGAR_OK) {
|
705
|
+
return status;
|
706
|
+
}
|
707
|
+
swap->total = vmstat.swpages * sigar->pagesize;
|
708
|
+
swap->used = vmstat.swpginuse * sigar->pagesize;
|
709
|
+
swap->free = swap->total - swap->used;
|
710
|
+
swap->page_in = vmstat.pageins;
|
711
|
+
swap->page_out = vmstat.pdpageouts;
|
712
|
+
#endif
|
713
|
+
|
714
|
+
return SIGAR_OK;
|
715
|
+
}
|
716
|
+
|
717
|
+
#ifndef KERN_CPTIME
|
718
|
+
#define KERN_CPTIME KERN_CP_TIME
|
719
|
+
#endif
|
720
|
+
|
721
|
+
#if defined(__NetBSD__)
|
722
|
+
typedef uint64_t cp_time_t;
|
723
|
+
#else
|
724
|
+
typedef unsigned long cp_time_t;
|
725
|
+
#endif
|
726
|
+
|
727
|
+
int sigar_cpu_get(sigar_t *sigar, sigar_cpu_t *cpu)
|
728
|
+
{
|
729
|
+
#if defined(DARWIN)
|
730
|
+
kern_return_t status;
|
731
|
+
mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
|
732
|
+
host_cpu_load_info_data_t cpuload;
|
733
|
+
|
734
|
+
status = host_statistics(sigar->mach_port, HOST_CPU_LOAD_INFO,
|
735
|
+
(host_info_t)&cpuload, &count);
|
736
|
+
|
737
|
+
if (status != KERN_SUCCESS) {
|
738
|
+
return errno;
|
739
|
+
}
|
740
|
+
|
741
|
+
cpu->user = SIGAR_TICK2MSEC(cpuload.cpu_ticks[CPU_STATE_USER]);
|
742
|
+
cpu->sys = SIGAR_TICK2MSEC(cpuload.cpu_ticks[CPU_STATE_SYSTEM]);
|
743
|
+
cpu->idle = SIGAR_TICK2MSEC(cpuload.cpu_ticks[CPU_STATE_IDLE]);
|
744
|
+
cpu->nice = SIGAR_TICK2MSEC(cpuload.cpu_ticks[CPU_STATE_NICE]);
|
745
|
+
cpu->wait = 0; /*N/A*/
|
746
|
+
cpu->irq = 0; /*N/A*/
|
747
|
+
cpu->soft_irq = 0; /*N/A*/
|
748
|
+
cpu->stolen = 0; /*N/A*/
|
749
|
+
cpu->total = cpu->user + cpu->nice + cpu->sys + cpu->idle;
|
750
|
+
|
751
|
+
#elif defined(__FreeBSD__) || (__OpenBSD__) || defined(__NetBSD__)
|
752
|
+
int status;
|
753
|
+
cp_time_t cp_time[CPUSTATES];
|
754
|
+
size_t size = sizeof(cp_time);
|
755
|
+
|
756
|
+
# if defined(__OpenBSD__) || defined(__NetBSD__)
|
757
|
+
int mib[] = { CTL_KERN, KERN_CPTIME };
|
758
|
+
if (sysctl(mib, NMIB(mib), &cp_time, &size, NULL, 0) == -1) {
|
759
|
+
status = errno;
|
760
|
+
}
|
761
|
+
# else
|
762
|
+
/* try sysctl first, does not require /dev/kmem perms */
|
763
|
+
if (sysctlbyname("kern.cp_time", &cp_time, &size, NULL, 0) == -1) {
|
764
|
+
status = kread(sigar, &cp_time, sizeof(cp_time),
|
765
|
+
sigar->koffsets[KOFFSET_CPUINFO]);
|
766
|
+
}
|
767
|
+
# endif
|
768
|
+
else {
|
769
|
+
status = SIGAR_OK;
|
770
|
+
}
|
771
|
+
|
772
|
+
if (status != SIGAR_OK) {
|
773
|
+
return status;
|
774
|
+
}
|
775
|
+
|
776
|
+
cpu->user = SIGAR_TICK2MSEC(cp_time[CP_USER]);
|
777
|
+
cpu->nice = SIGAR_TICK2MSEC(cp_time[CP_NICE]);
|
778
|
+
cpu->sys = SIGAR_TICK2MSEC(cp_time[CP_SYS]);
|
779
|
+
cpu->idle = SIGAR_TICK2MSEC(cp_time[CP_IDLE]);
|
780
|
+
cpu->wait = 0; /*N/A*/
|
781
|
+
cpu->irq = SIGAR_TICK2MSEC(cp_time[CP_INTR]);
|
782
|
+
cpu->soft_irq = 0; /*N/A*/
|
783
|
+
cpu->stolen = 0; /*N/A*/
|
784
|
+
cpu->total = cpu->user + cpu->nice + cpu->sys + cpu->idle + cpu->irq;
|
785
|
+
#endif
|
786
|
+
|
787
|
+
return SIGAR_OK;
|
788
|
+
}
|
789
|
+
|
790
|
+
#if defined(__FreeBSD__) && (__FreeBSD_version >= 700000)
|
791
|
+
#define HAVE_KERN_CP_TIMES /* kern.cp_times came later than 7.0, not sure exactly when */
|
792
|
+
static int sigar_cp_times_get(sigar_t *sigar, sigar_cpu_list_t *cpulist)
|
793
|
+
{
|
794
|
+
int maxcpu, status;
|
795
|
+
size_t len = sizeof(maxcpu), size;
|
796
|
+
long *times;
|
797
|
+
|
798
|
+
if (sysctlbyname("kern.smp.maxcpus", &maxcpu, &len, NULL, 0) == -1) {
|
799
|
+
return errno;
|
800
|
+
}
|
801
|
+
|
802
|
+
size = sizeof(long) * maxcpu * CPUSTATES;
|
803
|
+
times = malloc(size);
|
804
|
+
if (sysctlbyname("kern.cp_times", times, &size, NULL, 0) == -1) {
|
805
|
+
status = errno;
|
806
|
+
}
|
807
|
+
else {
|
808
|
+
int i, maxid = (size / CPUSTATES / sizeof(long));
|
809
|
+
long *cp_time = times;
|
810
|
+
status = SIGAR_OK;
|
811
|
+
|
812
|
+
for (i=0; i<maxid; i++) {
|
813
|
+
sigar_cpu_t *cpu;
|
814
|
+
|
815
|
+
SIGAR_CPU_LIST_GROW(cpulist);
|
816
|
+
|
817
|
+
cpu = &cpulist->data[cpulist->number++];
|
818
|
+
cpu->user = SIGAR_TICK2MSEC(cp_time[CP_USER]);
|
819
|
+
cpu->nice = SIGAR_TICK2MSEC(cp_time[CP_NICE]);
|
820
|
+
cpu->sys = SIGAR_TICK2MSEC(cp_time[CP_SYS]);
|
821
|
+
cpu->idle = SIGAR_TICK2MSEC(cp_time[CP_IDLE]);
|
822
|
+
cpu->wait = 0; /*N/A*/
|
823
|
+
cpu->irq = SIGAR_TICK2MSEC(cp_time[CP_INTR]);
|
824
|
+
cpu->soft_irq = 0; /*N/A*/
|
825
|
+
cpu->stolen = 0; /*N/A*/
|
826
|
+
cpu->total = cpu->user + cpu->nice + cpu->sys + cpu->idle + cpu->irq;
|
827
|
+
cp_time += CPUSTATES;
|
828
|
+
}
|
829
|
+
}
|
830
|
+
|
831
|
+
free(times);
|
832
|
+
return status;
|
833
|
+
}
|
834
|
+
#endif
|
835
|
+
|
836
|
+
int sigar_cpu_list_get(sigar_t *sigar, sigar_cpu_list_t *cpulist)
|
837
|
+
{
|
838
|
+
#ifdef DARWIN
|
839
|
+
kern_return_t status;
|
840
|
+
mach_msg_type_number_t count;
|
841
|
+
processor_cpu_load_info_data_t *cpuload;
|
842
|
+
natural_t i, ncpu;
|
843
|
+
|
844
|
+
status = host_processor_info(sigar->mach_port,
|
845
|
+
PROCESSOR_CPU_LOAD_INFO,
|
846
|
+
&ncpu,
|
847
|
+
(processor_info_array_t*)&cpuload,
|
848
|
+
&count);
|
849
|
+
|
850
|
+
if (status != KERN_SUCCESS) {
|
851
|
+
return errno;
|
852
|
+
}
|
853
|
+
|
854
|
+
sigar_cpu_list_create(cpulist);
|
855
|
+
|
856
|
+
for (i=0; i<ncpu; i++) {
|
857
|
+
sigar_cpu_t *cpu;
|
858
|
+
|
859
|
+
SIGAR_CPU_LIST_GROW(cpulist);
|
860
|
+
|
861
|
+
cpu = &cpulist->data[cpulist->number++];
|
862
|
+
|
863
|
+
cpu->user = SIGAR_TICK2MSEC(cpuload[i].cpu_ticks[CPU_STATE_USER]);
|
864
|
+
cpu->sys = SIGAR_TICK2MSEC(cpuload[i].cpu_ticks[CPU_STATE_SYSTEM]);
|
865
|
+
cpu->idle = SIGAR_TICK2MSEC(cpuload[i].cpu_ticks[CPU_STATE_IDLE]);
|
866
|
+
cpu->nice = SIGAR_TICK2MSEC(cpuload[i].cpu_ticks[CPU_STATE_NICE]);
|
867
|
+
cpu->wait = 0; /*N/A*/
|
868
|
+
cpu->irq = 0; /*N/A*/
|
869
|
+
cpu->soft_irq = 0; /*N/A*/
|
870
|
+
cpu->stolen = 0; /*N/A*/
|
871
|
+
cpu->total = cpu->user + cpu->nice + cpu->sys + cpu->idle;
|
872
|
+
}
|
873
|
+
|
874
|
+
vm_deallocate(mach_task_self(), (vm_address_t)cpuload, count);
|
875
|
+
|
876
|
+
return SIGAR_OK;
|
877
|
+
#else
|
878
|
+
int status, i;
|
879
|
+
sigar_cpu_t *cpu;
|
880
|
+
|
881
|
+
sigar_cpu_list_create(cpulist);
|
882
|
+
|
883
|
+
#ifdef HAVE_KERN_CP_TIMES
|
884
|
+
if ((status = sigar_cp_times_get(sigar, cpulist)) == SIGAR_OK) {
|
885
|
+
return SIGAR_OK;
|
886
|
+
}
|
887
|
+
#endif
|
888
|
+
/* XXX no multi cpu in freebsd < 7.0, howbout others?
|
889
|
+
* for now just report all metrics on the 1st cpu
|
890
|
+
* 0's for the rest
|
891
|
+
*/
|
892
|
+
cpu = &cpulist->data[cpulist->number++];
|
893
|
+
|
894
|
+
status = sigar_cpu_get(sigar, cpu);
|
895
|
+
if (status != SIGAR_OK) {
|
896
|
+
return status;
|
897
|
+
}
|
898
|
+
|
899
|
+
for (i=1; i<sigar->ncpu; i++) {
|
900
|
+
SIGAR_CPU_LIST_GROW(cpulist);
|
901
|
+
|
902
|
+
cpu = &cpulist->data[cpulist->number++];
|
903
|
+
SIGAR_ZERO(cpu);
|
904
|
+
}
|
905
|
+
|
906
|
+
return SIGAR_OK;
|
907
|
+
#endif
|
908
|
+
}
|
909
|
+
|
910
|
+
int sigar_uptime_get(sigar_t *sigar,
|
911
|
+
sigar_uptime_t *uptime)
|
912
|
+
{
|
913
|
+
uptime->uptime = time(NULL) - sigar->boot_time;
|
914
|
+
|
915
|
+
return SIGAR_OK;
|
916
|
+
}
|
917
|
+
|
918
|
+
int sigar_loadavg_get(sigar_t *sigar,
|
919
|
+
sigar_loadavg_t *loadavg)
|
920
|
+
{
|
921
|
+
getloadavg(loadavg->loadavg, 3);
|
922
|
+
|
923
|
+
return SIGAR_OK;
|
924
|
+
}
|
925
|
+
|
926
|
+
#if defined(DARWIN) && defined(DARWIN_HAS_LIBPROC_H)
|
927
|
+
|
928
|
+
static int proc_fdinfo_get(sigar_t *sigar, sigar_pid_t pid, int *num)
|
929
|
+
{
|
930
|
+
int rsize;
|
931
|
+
const int init_size = PROC_PIDLISTFD_SIZE * 32;
|
932
|
+
|
933
|
+
if (!sigar->libproc) {
|
934
|
+
return SIGAR_ENOTIMPL;
|
935
|
+
}
|
936
|
+
|
937
|
+
if (sigar->ifconf_len == 0) {
|
938
|
+
sigar->ifconf_len = init_size;
|
939
|
+
sigar->ifconf_buf = malloc(sigar->ifconf_len);
|
940
|
+
}
|
941
|
+
|
942
|
+
while (1) {
|
943
|
+
rsize = sigar->proc_pidinfo(pid, PROC_PIDLISTFDS, 0,
|
944
|
+
sigar->ifconf_buf, sigar->ifconf_len);
|
945
|
+
if (rsize <= 0) {
|
946
|
+
return errno;
|
947
|
+
}
|
948
|
+
if ((rsize + PROC_PIDLISTFD_SIZE) < sigar->ifconf_len) {
|
949
|
+
break;
|
950
|
+
}
|
951
|
+
|
952
|
+
sigar->ifconf_len += init_size;
|
953
|
+
sigar->ifconf_buf = realloc(sigar->ifconf_buf, sigar->ifconf_len);
|
954
|
+
}
|
955
|
+
|
956
|
+
*num = rsize / PROC_PIDLISTFD_SIZE;
|
957
|
+
|
958
|
+
return SIGAR_OK;
|
959
|
+
}
|
960
|
+
|
961
|
+
#endif
|
962
|
+
|
963
|
+
#ifndef KERN_PROC_PROC
|
964
|
+
/* freebsd 4.x */
|
965
|
+
#define KERN_PROC_PROC KERN_PROC_ALL
|
966
|
+
#endif
|
967
|
+
|
968
|
+
int sigar_os_proc_list_get(sigar_t *sigar,
|
969
|
+
sigar_proc_list_t *proclist)
|
970
|
+
{
|
971
|
+
#if defined(DARWIN) || defined(SIGAR_FREEBSD5) || defined(__OpenBSD__) || defined(__NetBSD__)
|
972
|
+
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0 };
|
973
|
+
int i, num;
|
974
|
+
size_t len;
|
975
|
+
struct kinfo_proc *proc;
|
976
|
+
|
977
|
+
if (sysctl(mib, NMIB(mib), NULL, &len, NULL, 0) < 0) {
|
978
|
+
return errno;
|
979
|
+
}
|
980
|
+
|
981
|
+
proc = malloc(len);
|
982
|
+
|
983
|
+
if (sysctl(mib, NMIB(mib), proc, &len, NULL, 0) < 0) {
|
984
|
+
free(proc);
|
985
|
+
return errno;
|
986
|
+
}
|
987
|
+
|
988
|
+
num = len/sizeof(*proc);
|
989
|
+
|
990
|
+
for (i=0; i<num; i++) {
|
991
|
+
if (proc[i].KI_FLAG & P_SYSTEM) {
|
992
|
+
continue;
|
993
|
+
}
|
994
|
+
if (proc[i].KI_PID == 0) {
|
995
|
+
continue;
|
996
|
+
}
|
997
|
+
SIGAR_PROC_LIST_GROW(proclist);
|
998
|
+
proclist->data[proclist->number++] = proc[i].KI_PID;
|
999
|
+
}
|
1000
|
+
|
1001
|
+
free(proc);
|
1002
|
+
|
1003
|
+
return SIGAR_OK;
|
1004
|
+
#else
|
1005
|
+
int i, num;
|
1006
|
+
struct kinfo_proc *proc;
|
1007
|
+
|
1008
|
+
if (!sigar->kmem) {
|
1009
|
+
return SIGAR_EPERM_KMEM;
|
1010
|
+
}
|
1011
|
+
|
1012
|
+
proc = kvm_getprocs(sigar->kmem, KERN_PROC_PROC, 0, &num);
|
1013
|
+
|
1014
|
+
for (i=0; i<num; i++) {
|
1015
|
+
if (proc[i].KI_FLAG & P_SYSTEM) {
|
1016
|
+
continue;
|
1017
|
+
}
|
1018
|
+
SIGAR_PROC_LIST_GROW(proclist);
|
1019
|
+
proclist->data[proclist->number++] = proc[i].KI_PID;
|
1020
|
+
}
|
1021
|
+
#endif
|
1022
|
+
|
1023
|
+
return SIGAR_OK;
|
1024
|
+
}
|
1025
|
+
|
1026
|
+
static int sigar_get_pinfo(sigar_t *sigar, sigar_pid_t pid)
|
1027
|
+
{
|
1028
|
+
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
1029
|
+
int mib[] = { CTL_KERN, KERN_PROC2, KERN_PROC_PID, 0, sizeof(*sigar->pinfo), 1 };
|
1030
|
+
#else
|
1031
|
+
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, 0 };
|
1032
|
+
#endif
|
1033
|
+
size_t len = sizeof(*sigar->pinfo);
|
1034
|
+
time_t timenow = time(NULL);
|
1035
|
+
mib[3] = pid;
|
1036
|
+
|
1037
|
+
if (sigar->pinfo == NULL) {
|
1038
|
+
sigar->pinfo = malloc(len);
|
1039
|
+
}
|
1040
|
+
|
1041
|
+
if (sigar->last_pid == pid) {
|
1042
|
+
if ((timenow - sigar->last_getprocs) < SIGAR_LAST_PROC_EXPIRE) {
|
1043
|
+
return SIGAR_OK;
|
1044
|
+
}
|
1045
|
+
}
|
1046
|
+
|
1047
|
+
sigar->last_pid = pid;
|
1048
|
+
sigar->last_getprocs = timenow;
|
1049
|
+
|
1050
|
+
if (sysctl(mib, NMIB(mib), sigar->pinfo, &len, NULL, 0) < 0) {
|
1051
|
+
return errno;
|
1052
|
+
}
|
1053
|
+
|
1054
|
+
return SIGAR_OK;
|
1055
|
+
}
|
1056
|
+
|
1057
|
+
#ifdef DARWIN
|
1058
|
+
#define GLOBAL_SHARED_SIZE (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE)
|
1059
|
+
#endif
|
1060
|
+
|
1061
|
+
int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
|
1062
|
+
sigar_proc_mem_t *procmem)
|
1063
|
+
{
|
1064
|
+
#if defined(DARWIN)
|
1065
|
+
mach_port_t task, self = mach_task_self();
|
1066
|
+
kern_return_t status;
|
1067
|
+
task_basic_info_data_t info;
|
1068
|
+
task_events_info_data_t events;
|
1069
|
+
mach_msg_type_number_t count;
|
1070
|
+
# ifdef DARWIN_HAS_LIBPROC_H
|
1071
|
+
struct proc_taskinfo pti;
|
1072
|
+
struct proc_regioninfo pri;
|
1073
|
+
|
1074
|
+
if (sigar->libproc) {
|
1075
|
+
int sz =
|
1076
|
+
sigar->proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &pti, sizeof(pti));
|
1077
|
+
|
1078
|
+
if (sz == sizeof(pti)) {
|
1079
|
+
procmem->size = pti.pti_virtual_size;
|
1080
|
+
procmem->resident = pti.pti_resident_size;
|
1081
|
+
procmem->page_faults = pti.pti_faults;
|
1082
|
+
procmem->minor_faults = SIGAR_FIELD_NOTIMPL;
|
1083
|
+
procmem->major_faults = SIGAR_FIELD_NOTIMPL;
|
1084
|
+
procmem->share = SIGAR_FIELD_NOTIMPL;
|
1085
|
+
|
1086
|
+
sz = sigar->proc_pidinfo(pid, PROC_PIDREGIONINFO, 0, &pri, sizeof(pri));
|
1087
|
+
if (sz == sizeof(pri)) {
|
1088
|
+
if ((pri.pri_share_mode == SM_EMPTY) &&
|
1089
|
+
(procmem->size > GLOBAL_SHARED_SIZE))
|
1090
|
+
{
|
1091
|
+
procmem->size -= GLOBAL_SHARED_SIZE; /* SIGAR-123 */
|
1092
|
+
}
|
1093
|
+
}
|
1094
|
+
return SIGAR_OK;
|
1095
|
+
}
|
1096
|
+
}
|
1097
|
+
# endif
|
1098
|
+
|
1099
|
+
status = task_for_pid(self, pid, &task);
|
1100
|
+
|
1101
|
+
if (status != KERN_SUCCESS) {
|
1102
|
+
return errno;
|
1103
|
+
}
|
1104
|
+
|
1105
|
+
count = TASK_BASIC_INFO_COUNT;
|
1106
|
+
status = task_info(task, TASK_BASIC_INFO, (task_info_t)&info, &count);
|
1107
|
+
if (status != KERN_SUCCESS) {
|
1108
|
+
return errno;
|
1109
|
+
}
|
1110
|
+
|
1111
|
+
count = TASK_EVENTS_INFO_COUNT;
|
1112
|
+
status = task_info(task, TASK_EVENTS_INFO, (task_info_t)&events, &count);
|
1113
|
+
if (status == KERN_SUCCESS) {
|
1114
|
+
procmem->page_faults = events.faults;
|
1115
|
+
}
|
1116
|
+
else {
|
1117
|
+
procmem->page_faults = SIGAR_FIELD_NOTIMPL;
|
1118
|
+
}
|
1119
|
+
|
1120
|
+
procmem->minor_faults = SIGAR_FIELD_NOTIMPL;
|
1121
|
+
procmem->major_faults = SIGAR_FIELD_NOTIMPL;
|
1122
|
+
|
1123
|
+
if (task != self) {
|
1124
|
+
mach_port_deallocate(self, task);
|
1125
|
+
}
|
1126
|
+
|
1127
|
+
procmem->size = info.virtual_size;
|
1128
|
+
procmem->resident = info.resident_size;
|
1129
|
+
procmem->share = SIGAR_FIELD_NOTIMPL;
|
1130
|
+
|
1131
|
+
return SIGAR_OK;
|
1132
|
+
#elif defined(__FreeBSD__)
|
1133
|
+
int status = sigar_get_pinfo(sigar, pid);
|
1134
|
+
bsd_pinfo_t *pinfo = sigar->pinfo;
|
1135
|
+
|
1136
|
+
if (status != SIGAR_OK) {
|
1137
|
+
return status;
|
1138
|
+
}
|
1139
|
+
|
1140
|
+
procmem->size =
|
1141
|
+
(pinfo->KI_TSZ + pinfo->KI_DSZ + pinfo->KI_SSZ) * sigar->pagesize;
|
1142
|
+
|
1143
|
+
procmem->resident = pinfo->KI_RSS * sigar->pagesize;
|
1144
|
+
|
1145
|
+
procmem->share = SIGAR_FIELD_NOTIMPL;
|
1146
|
+
|
1147
|
+
procmem->page_faults = SIGAR_FIELD_NOTIMPL;
|
1148
|
+
procmem->minor_faults = SIGAR_FIELD_NOTIMPL;
|
1149
|
+
procmem->major_faults = SIGAR_FIELD_NOTIMPL;
|
1150
|
+
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
1151
|
+
int status = sigar_get_pinfo(sigar, pid);
|
1152
|
+
bsd_pinfo_t *pinfo = sigar->pinfo;
|
1153
|
+
|
1154
|
+
if (status != SIGAR_OK) {
|
1155
|
+
return status;
|
1156
|
+
}
|
1157
|
+
|
1158
|
+
procmem->size =
|
1159
|
+
(pinfo->p_vm_tsize + pinfo->p_vm_dsize + pinfo->p_vm_ssize) * sigar->pagesize;
|
1160
|
+
|
1161
|
+
procmem->resident = pinfo->p_vm_rssize * sigar->pagesize;
|
1162
|
+
|
1163
|
+
procmem->share = SIGAR_FIELD_NOTIMPL;
|
1164
|
+
|
1165
|
+
procmem->minor_faults = pinfo->p_uru_minflt;
|
1166
|
+
procmem->major_faults = pinfo->p_uru_majflt;
|
1167
|
+
procmem->page_faults = procmem->minor_faults + procmem->major_faults;
|
1168
|
+
#endif
|
1169
|
+
return SIGAR_OK;
|
1170
|
+
}
|
1171
|
+
|
1172
|
+
int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid,
|
1173
|
+
sigar_proc_cred_t *proccred)
|
1174
|
+
{
|
1175
|
+
int status = sigar_get_pinfo(sigar, pid);
|
1176
|
+
bsd_pinfo_t *pinfo = sigar->pinfo;
|
1177
|
+
|
1178
|
+
if (status != SIGAR_OK) {
|
1179
|
+
return status;
|
1180
|
+
}
|
1181
|
+
|
1182
|
+
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
1183
|
+
proccred->uid = pinfo->p_ruid;
|
1184
|
+
proccred->gid = pinfo->p_rgid;
|
1185
|
+
proccred->euid = pinfo->p_uid;
|
1186
|
+
proccred->egid = pinfo->p_gid;
|
1187
|
+
#else
|
1188
|
+
proccred->uid = pinfo->KI_UID;
|
1189
|
+
proccred->gid = pinfo->KI_GID;
|
1190
|
+
proccred->euid = pinfo->KI_EUID;
|
1191
|
+
proccred->egid = pinfo->KI_EGID;
|
1192
|
+
#endif
|
1193
|
+
|
1194
|
+
return SIGAR_OK;
|
1195
|
+
}
|
1196
|
+
|
1197
|
+
#define tv2msec(tv) \
|
1198
|
+
(((sigar_uint64_t)tv.tv_sec * SIGAR_MSEC) + (((sigar_uint64_t)tv.tv_usec) / 1000))
|
1199
|
+
|
1200
|
+
#ifdef DARWIN
|
1201
|
+
#define tval2msec(tval) \
|
1202
|
+
((tval.seconds * SIGAR_MSEC) + (tval.microseconds / 1000))
|
1203
|
+
|
1204
|
+
#define tval2nsec(tval) \
|
1205
|
+
(SIGAR_SEC2NANO((tval).seconds) + SIGAR_MICROSEC2NANO((tval).microseconds))
|
1206
|
+
|
1207
|
+
static int get_proc_times(sigar_t *sigar, sigar_pid_t pid, sigar_proc_time_t *time)
|
1208
|
+
{
|
1209
|
+
unsigned int count;
|
1210
|
+
time_value_t utime = {0, 0}, stime = {0, 0};
|
1211
|
+
task_basic_info_data_t ti;
|
1212
|
+
task_thread_times_info_data_t tti;
|
1213
|
+
task_port_t task, self;
|
1214
|
+
kern_return_t status;
|
1215
|
+
# ifdef DARWIN_HAS_LIBPROC_H
|
1216
|
+
if (sigar->libproc) {
|
1217
|
+
struct proc_taskinfo pti;
|
1218
|
+
int sz =
|
1219
|
+
sigar->proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &pti, sizeof(pti));
|
1220
|
+
|
1221
|
+
if (sz == sizeof(pti)) {
|
1222
|
+
time->user = SIGAR_NSEC2MSEC(pti.pti_total_user);
|
1223
|
+
time->sys = SIGAR_NSEC2MSEC(pti.pti_total_system);
|
1224
|
+
time->total = time->user + time->sys;
|
1225
|
+
return SIGAR_OK;
|
1226
|
+
}
|
1227
|
+
}
|
1228
|
+
# endif
|
1229
|
+
|
1230
|
+
self = mach_task_self();
|
1231
|
+
status = task_for_pid(self, pid, &task);
|
1232
|
+
if (status != KERN_SUCCESS) {
|
1233
|
+
return errno;
|
1234
|
+
}
|
1235
|
+
|
1236
|
+
count = TASK_BASIC_INFO_COUNT;
|
1237
|
+
status = task_info(task, TASK_BASIC_INFO,
|
1238
|
+
(task_info_t)&ti, &count);
|
1239
|
+
if (status != KERN_SUCCESS) {
|
1240
|
+
if (task != self) {
|
1241
|
+
mach_port_deallocate(self, task);
|
1242
|
+
}
|
1243
|
+
return errno;
|
1244
|
+
}
|
1245
|
+
|
1246
|
+
count = TASK_THREAD_TIMES_INFO_COUNT;
|
1247
|
+
status = task_info(task, TASK_THREAD_TIMES_INFO,
|
1248
|
+
(task_info_t)&tti, &count);
|
1249
|
+
if (status != KERN_SUCCESS) {
|
1250
|
+
if (task != self) {
|
1251
|
+
mach_port_deallocate(self, task);
|
1252
|
+
}
|
1253
|
+
return errno;
|
1254
|
+
}
|
1255
|
+
|
1256
|
+
time_value_add(&utime, &ti.user_time);
|
1257
|
+
time_value_add(&stime, &ti.system_time);
|
1258
|
+
time_value_add(&utime, &tti.user_time);
|
1259
|
+
time_value_add(&stime, &tti.system_time);
|
1260
|
+
|
1261
|
+
time->user = tval2msec(utime);
|
1262
|
+
time->sys = tval2msec(stime);
|
1263
|
+
time->total = time->user + time->sys;
|
1264
|
+
|
1265
|
+
return SIGAR_OK;
|
1266
|
+
}
|
1267
|
+
#endif
|
1268
|
+
|
1269
|
+
int sigar_proc_time_get(sigar_t *sigar, sigar_pid_t pid,
|
1270
|
+
sigar_proc_time_t *proctime)
|
1271
|
+
{
|
1272
|
+
#ifdef SIGAR_FREEBSD4
|
1273
|
+
struct user user;
|
1274
|
+
#endif
|
1275
|
+
int status = sigar_get_pinfo(sigar, pid);
|
1276
|
+
bsd_pinfo_t *pinfo = sigar->pinfo;
|
1277
|
+
|
1278
|
+
if (status != SIGAR_OK) {
|
1279
|
+
return status;
|
1280
|
+
}
|
1281
|
+
|
1282
|
+
#if defined(DARWIN)
|
1283
|
+
if ((status = get_proc_times(sigar, pid, proctime)) != SIGAR_OK) {
|
1284
|
+
return status;
|
1285
|
+
}
|
1286
|
+
proctime->start_time = tv2msec(pinfo->KI_START);
|
1287
|
+
#elif defined(SIGAR_FREEBSD5)
|
1288
|
+
proctime->user = tv2msec(pinfo->ki_rusage.ru_utime);
|
1289
|
+
proctime->sys = tv2msec(pinfo->ki_rusage.ru_stime);
|
1290
|
+
proctime->total = proctime->user + proctime->sys;
|
1291
|
+
proctime->start_time = tv2msec(pinfo->KI_START);
|
1292
|
+
#elif defined(SIGAR_FREEBSD4)
|
1293
|
+
if (!sigar->kmem) {
|
1294
|
+
return SIGAR_EPERM_KMEM;
|
1295
|
+
}
|
1296
|
+
|
1297
|
+
status = kread(sigar, &user, sizeof(user),
|
1298
|
+
(u_long)pinfo->kp_proc.p_addr);
|
1299
|
+
if (status != SIGAR_OK) {
|
1300
|
+
return status;
|
1301
|
+
}
|
1302
|
+
|
1303
|
+
proctime->user = tv2msec(user.u_stats.p_ru.ru_utime);
|
1304
|
+
proctime->sys = tv2msec(user.u_stats.p_ru.ru_stime);
|
1305
|
+
proctime->total = proctime->user + proctime->sys;
|
1306
|
+
proctime->start_time = tv2msec(user.u_stats.p_start);
|
1307
|
+
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
1308
|
+
/* XXX *_usec */
|
1309
|
+
proctime->user = pinfo->p_uutime_sec * SIGAR_MSEC;
|
1310
|
+
proctime->sys = pinfo->p_ustime_sec * SIGAR_MSEC;
|
1311
|
+
proctime->total = proctime->user + proctime->sys;
|
1312
|
+
proctime->start_time = pinfo->p_ustart_sec * SIGAR_MSEC;
|
1313
|
+
#endif
|
1314
|
+
|
1315
|
+
return SIGAR_OK;
|
1316
|
+
}
|
1317
|
+
|
1318
|
+
#ifdef DARWIN
|
1319
|
+
/* thread state mapping derived from ps.tproj */
|
1320
|
+
static const char const thread_states[] = {
|
1321
|
+
/*0*/ '-',
|
1322
|
+
/*1*/ SIGAR_PROC_STATE_RUN,
|
1323
|
+
/*2*/ SIGAR_PROC_STATE_ZOMBIE,
|
1324
|
+
/*3*/ SIGAR_PROC_STATE_SLEEP,
|
1325
|
+
/*4*/ SIGAR_PROC_STATE_IDLE,
|
1326
|
+
/*5*/ SIGAR_PROC_STATE_STOP,
|
1327
|
+
/*6*/ SIGAR_PROC_STATE_STOP,
|
1328
|
+
/*7*/ '?'
|
1329
|
+
};
|
1330
|
+
|
1331
|
+
static int thread_state_get(thread_basic_info_data_t *info)
|
1332
|
+
{
|
1333
|
+
switch (info->run_state) {
|
1334
|
+
case TH_STATE_RUNNING:
|
1335
|
+
return 1;
|
1336
|
+
case TH_STATE_UNINTERRUPTIBLE:
|
1337
|
+
return 2;
|
1338
|
+
case TH_STATE_WAITING:
|
1339
|
+
return (info->sleep_time > 20) ? 4 : 3;
|
1340
|
+
case TH_STATE_STOPPED:
|
1341
|
+
return 5;
|
1342
|
+
case TH_STATE_HALTED:
|
1343
|
+
return 6;
|
1344
|
+
default:
|
1345
|
+
return 7;
|
1346
|
+
}
|
1347
|
+
}
|
1348
|
+
|
1349
|
+
static int sigar_proc_threads_get(sigar_t *sigar, sigar_pid_t pid,
|
1350
|
+
sigar_proc_state_t *procstate)
|
1351
|
+
{
|
1352
|
+
mach_port_t task, self = mach_task_self();
|
1353
|
+
kern_return_t status;
|
1354
|
+
thread_array_t threads;
|
1355
|
+
mach_msg_type_number_t count, i;
|
1356
|
+
int state = TH_STATE_HALTED + 1;
|
1357
|
+
|
1358
|
+
status = task_for_pid(self, pid, &task);
|
1359
|
+
if (status != KERN_SUCCESS) {
|
1360
|
+
return errno;
|
1361
|
+
}
|
1362
|
+
|
1363
|
+
status = task_threads(task, &threads, &count);
|
1364
|
+
if (status != KERN_SUCCESS) {
|
1365
|
+
return errno;
|
1366
|
+
}
|
1367
|
+
|
1368
|
+
procstate->threads = count;
|
1369
|
+
|
1370
|
+
for (i=0; i<count; i++) {
|
1371
|
+
mach_msg_type_number_t info_count = THREAD_BASIC_INFO_COUNT;
|
1372
|
+
thread_basic_info_data_t info;
|
1373
|
+
|
1374
|
+
status = thread_info(threads[i], THREAD_BASIC_INFO,
|
1375
|
+
(thread_info_t)&info, &info_count);
|
1376
|
+
if (status == KERN_SUCCESS) {
|
1377
|
+
int tstate = thread_state_get(&info);
|
1378
|
+
if (tstate < state) {
|
1379
|
+
state = tstate;
|
1380
|
+
}
|
1381
|
+
}
|
1382
|
+
}
|
1383
|
+
|
1384
|
+
vm_deallocate(self, (vm_address_t)threads, sizeof(thread_t) * count);
|
1385
|
+
|
1386
|
+
procstate->state = thread_states[state];
|
1387
|
+
|
1388
|
+
return SIGAR_OK;
|
1389
|
+
}
|
1390
|
+
#endif
|
1391
|
+
|
1392
|
+
int sigar_proc_state_get(sigar_t *sigar, sigar_pid_t pid,
|
1393
|
+
sigar_proc_state_t *procstate)
|
1394
|
+
{
|
1395
|
+
int status = sigar_get_pinfo(sigar, pid);
|
1396
|
+
bsd_pinfo_t *pinfo = sigar->pinfo;
|
1397
|
+
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
1398
|
+
int state = pinfo->p_stat;
|
1399
|
+
#else
|
1400
|
+
int state = pinfo->KI_STAT;
|
1401
|
+
#endif
|
1402
|
+
|
1403
|
+
if (status != SIGAR_OK) {
|
1404
|
+
return status;
|
1405
|
+
}
|
1406
|
+
|
1407
|
+
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
1408
|
+
SIGAR_SSTRCPY(procstate->name, pinfo->p_comm);
|
1409
|
+
procstate->ppid = pinfo->p_ppid;
|
1410
|
+
procstate->priority = pinfo->p_priority;
|
1411
|
+
procstate->nice = pinfo->p_nice;
|
1412
|
+
procstate->tty = pinfo->p_tdev;
|
1413
|
+
procstate->threads = SIGAR_FIELD_NOTIMPL;
|
1414
|
+
procstate->processor = pinfo->p_cpuid;
|
1415
|
+
#else
|
1416
|
+
SIGAR_SSTRCPY(procstate->name, pinfo->KI_COMM);
|
1417
|
+
procstate->ppid = pinfo->KI_PPID;
|
1418
|
+
procstate->priority = pinfo->KI_PRI;
|
1419
|
+
procstate->nice = pinfo->KI_NICE;
|
1420
|
+
procstate->tty = SIGAR_FIELD_NOTIMPL; /*XXX*/
|
1421
|
+
procstate->threads = SIGAR_FIELD_NOTIMPL;
|
1422
|
+
procstate->processor = SIGAR_FIELD_NOTIMPL;
|
1423
|
+
#endif
|
1424
|
+
|
1425
|
+
#ifdef DARWIN
|
1426
|
+
status = sigar_proc_threads_get(sigar, pid, procstate);
|
1427
|
+
if (status == SIGAR_OK) {
|
1428
|
+
return status;
|
1429
|
+
}
|
1430
|
+
#endif
|
1431
|
+
|
1432
|
+
switch (state) {
|
1433
|
+
case SIDL:
|
1434
|
+
procstate->state = 'D';
|
1435
|
+
break;
|
1436
|
+
case SRUN:
|
1437
|
+
#ifdef SONPROC
|
1438
|
+
case SONPROC:
|
1439
|
+
#endif
|
1440
|
+
procstate->state = 'R';
|
1441
|
+
break;
|
1442
|
+
case SSLEEP:
|
1443
|
+
procstate->state = 'S';
|
1444
|
+
break;
|
1445
|
+
case SSTOP:
|
1446
|
+
procstate->state = 'T';
|
1447
|
+
break;
|
1448
|
+
case SZOMB:
|
1449
|
+
procstate->state = 'Z';
|
1450
|
+
break;
|
1451
|
+
default:
|
1452
|
+
procstate->state = '?';
|
1453
|
+
break;
|
1454
|
+
}
|
1455
|
+
|
1456
|
+
return SIGAR_OK;
|
1457
|
+
}
|
1458
|
+
|
1459
|
+
#if defined(DARWIN)
|
1460
|
+
typedef struct {
|
1461
|
+
char *buf, *ptr, *end;
|
1462
|
+
int count;
|
1463
|
+
} sigar_kern_proc_args_t;
|
1464
|
+
|
1465
|
+
static void sigar_kern_proc_args_destroy(sigar_kern_proc_args_t *kargs)
|
1466
|
+
{
|
1467
|
+
if (kargs->buf) {
|
1468
|
+
free(kargs->buf);
|
1469
|
+
kargs->buf = NULL;
|
1470
|
+
}
|
1471
|
+
}
|
1472
|
+
|
1473
|
+
/* re-usable hack for use by proc_args and proc_env */
|
1474
|
+
static int sigar_kern_proc_args_get(sigar_t *sigar,
|
1475
|
+
sigar_pid_t pid,
|
1476
|
+
char *exe,
|
1477
|
+
sigar_kern_proc_args_t *kargs)
|
1478
|
+
{
|
1479
|
+
/*
|
1480
|
+
* derived from:
|
1481
|
+
* http://darwinsource.opendarwin.org/10.4.1/adv_cmds-79.1/ps.tproj/print.c
|
1482
|
+
*/
|
1483
|
+
int mib[3], len;
|
1484
|
+
size_t size = sigar_argmax_get(sigar);
|
1485
|
+
|
1486
|
+
kargs->buf = malloc(size);
|
1487
|
+
|
1488
|
+
mib[0] = CTL_KERN;
|
1489
|
+
mib[1] = KERN_PROCARGS2;
|
1490
|
+
mib[2] = pid;
|
1491
|
+
|
1492
|
+
if (sysctl(mib, NMIB(mib), kargs->buf, &size, NULL, 0) < 0) {
|
1493
|
+
sigar_kern_proc_args_destroy(kargs);
|
1494
|
+
return errno;
|
1495
|
+
}
|
1496
|
+
|
1497
|
+
kargs->end = &kargs->buf[size];
|
1498
|
+
|
1499
|
+
memcpy(&kargs->count, kargs->buf, sizeof(kargs->count));
|
1500
|
+
kargs->ptr = kargs->buf + sizeof(kargs->count);
|
1501
|
+
|
1502
|
+
len = strlen(kargs->ptr);
|
1503
|
+
if (exe) {
|
1504
|
+
memcpy(exe, kargs->ptr, len+1);
|
1505
|
+
}
|
1506
|
+
kargs->ptr += len+1;
|
1507
|
+
|
1508
|
+
if (kargs->ptr == kargs->end) {
|
1509
|
+
sigar_kern_proc_args_destroy(kargs);
|
1510
|
+
return exe ? SIGAR_OK : ENOENT;
|
1511
|
+
}
|
1512
|
+
|
1513
|
+
for (; kargs->ptr < kargs->end; kargs->ptr++) {
|
1514
|
+
if (*kargs->ptr != '\0') {
|
1515
|
+
break; /* start of argv[0] */
|
1516
|
+
}
|
1517
|
+
}
|
1518
|
+
|
1519
|
+
if (kargs->ptr == kargs->end) {
|
1520
|
+
sigar_kern_proc_args_destroy(kargs);
|
1521
|
+
return exe ? SIGAR_OK : ENOENT;
|
1522
|
+
}
|
1523
|
+
|
1524
|
+
return SIGAR_OK;
|
1525
|
+
}
|
1526
|
+
|
1527
|
+
static int kern_proc_args_skip_argv(sigar_kern_proc_args_t *kargs)
|
1528
|
+
{
|
1529
|
+
char *ptr = kargs->ptr;
|
1530
|
+
char *end = kargs->end;
|
1531
|
+
int count = kargs->count;
|
1532
|
+
|
1533
|
+
/* skip over argv */
|
1534
|
+
while ((ptr < end) && (count-- > 0)) {
|
1535
|
+
int alen = strlen(ptr)+1;
|
1536
|
+
|
1537
|
+
ptr += alen;
|
1538
|
+
}
|
1539
|
+
|
1540
|
+
kargs->ptr = ptr;
|
1541
|
+
kargs->end = end;
|
1542
|
+
kargs->count = 0;
|
1543
|
+
|
1544
|
+
if (ptr >= end) {
|
1545
|
+
return ENOENT;
|
1546
|
+
}
|
1547
|
+
|
1548
|
+
return SIGAR_OK;
|
1549
|
+
}
|
1550
|
+
#endif
|
1551
|
+
|
1552
|
+
int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid,
|
1553
|
+
sigar_proc_args_t *procargs)
|
1554
|
+
{
|
1555
|
+
#if defined(DARWIN)
|
1556
|
+
int status, count;
|
1557
|
+
sigar_kern_proc_args_t kargs;
|
1558
|
+
char *ptr, *end;
|
1559
|
+
|
1560
|
+
status = sigar_kern_proc_args_get(sigar, pid, NULL, &kargs);
|
1561
|
+
if (status != SIGAR_OK) {
|
1562
|
+
return status;
|
1563
|
+
}
|
1564
|
+
|
1565
|
+
count = kargs.count;
|
1566
|
+
ptr = kargs.ptr;
|
1567
|
+
end = kargs.end;
|
1568
|
+
|
1569
|
+
while ((ptr < end) && (count-- > 0)) {
|
1570
|
+
int slen = strlen(ptr);
|
1571
|
+
int alen = slen+1;
|
1572
|
+
char *arg;
|
1573
|
+
|
1574
|
+
/*
|
1575
|
+
* trim trailing whitespace.
|
1576
|
+
* seen w/ postgresql, probably related
|
1577
|
+
* to messing with argv[0]
|
1578
|
+
*/
|
1579
|
+
while (*(ptr + (slen-1)) == ' ') {
|
1580
|
+
if (--slen <= 0) {
|
1581
|
+
break;
|
1582
|
+
}
|
1583
|
+
}
|
1584
|
+
|
1585
|
+
arg = malloc(slen+1);
|
1586
|
+
|
1587
|
+
SIGAR_PROC_ARGS_GROW(procargs);
|
1588
|
+
memcpy(arg, ptr, slen);
|
1589
|
+
*(arg+slen) = '\0';
|
1590
|
+
|
1591
|
+
procargs->data[procargs->number++] = arg;
|
1592
|
+
|
1593
|
+
ptr += alen;
|
1594
|
+
}
|
1595
|
+
|
1596
|
+
sigar_kern_proc_args_destroy(&kargs);
|
1597
|
+
return SIGAR_OK;
|
1598
|
+
#elif defined(__FreeBSD__) || defined(__NetBSD__)
|
1599
|
+
char buffer[SIGAR_ARG_MAX+1], *ptr=buffer;
|
1600
|
+
size_t len = sizeof(buffer);
|
1601
|
+
# ifdef __NetBSD__
|
1602
|
+
int mib[] = { CTL_KERN, KERN_PROC_ARGS, 0, KERN_PROC_ARGV };
|
1603
|
+
mib[2] = pid;
|
1604
|
+
# else
|
1605
|
+
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, 0 };
|
1606
|
+
mib[3] = pid;
|
1607
|
+
# endif
|
1608
|
+
|
1609
|
+
if (sysctl(mib, NMIB(mib), buffer, &len, NULL, 0) < 0) {
|
1610
|
+
return errno;
|
1611
|
+
}
|
1612
|
+
|
1613
|
+
if (len == 0) {
|
1614
|
+
procargs->number = 0;
|
1615
|
+
return SIGAR_OK;
|
1616
|
+
}
|
1617
|
+
|
1618
|
+
buffer[len] = '\0';
|
1619
|
+
|
1620
|
+
while (len > 0) {
|
1621
|
+
int alen = strlen(ptr)+1;
|
1622
|
+
char *arg = malloc(alen);
|
1623
|
+
|
1624
|
+
SIGAR_PROC_ARGS_GROW(procargs);
|
1625
|
+
memcpy(arg, ptr, alen);
|
1626
|
+
|
1627
|
+
procargs->data[procargs->number++] = arg;
|
1628
|
+
|
1629
|
+
len -= alen;
|
1630
|
+
if (len > 0) {
|
1631
|
+
ptr += alen;
|
1632
|
+
}
|
1633
|
+
}
|
1634
|
+
|
1635
|
+
return SIGAR_OK;
|
1636
|
+
#elif defined(__OpenBSD__)
|
1637
|
+
char buffer[SIGAR_ARG_MAX+1], **ptr=(char **)buffer;
|
1638
|
+
size_t len = sizeof(buffer);
|
1639
|
+
int mib[] = { CTL_KERN, KERN_PROC_ARGS, 0, KERN_PROC_ARGV };
|
1640
|
+
mib[2] = pid;
|
1641
|
+
|
1642
|
+
if (sysctl(mib, NMIB(mib), buffer, &len, NULL, 0) < 0) {
|
1643
|
+
return errno;
|
1644
|
+
}
|
1645
|
+
|
1646
|
+
if (len == 0) {
|
1647
|
+
procargs->number = 0;
|
1648
|
+
return SIGAR_OK;
|
1649
|
+
}
|
1650
|
+
|
1651
|
+
for (; *ptr; ptr++) {
|
1652
|
+
int alen = strlen(*ptr)+1;
|
1653
|
+
char *arg = malloc(alen);
|
1654
|
+
|
1655
|
+
SIGAR_PROC_ARGS_GROW(procargs);
|
1656
|
+
memcpy(arg, *ptr, alen);
|
1657
|
+
|
1658
|
+
procargs->data[procargs->number++] = arg;
|
1659
|
+
}
|
1660
|
+
|
1661
|
+
return SIGAR_OK;
|
1662
|
+
#else
|
1663
|
+
return SIGAR_ENOTIMPL;
|
1664
|
+
#endif
|
1665
|
+
}
|
1666
|
+
|
1667
|
+
int sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid,
|
1668
|
+
sigar_proc_env_t *procenv)
|
1669
|
+
{
|
1670
|
+
#ifdef DARWIN
|
1671
|
+
int status, count;
|
1672
|
+
sigar_kern_proc_args_t kargs;
|
1673
|
+
char *ptr, *end;
|
1674
|
+
|
1675
|
+
status = sigar_kern_proc_args_get(sigar, pid, NULL, &kargs);
|
1676
|
+
if (status != SIGAR_OK) {
|
1677
|
+
return status;
|
1678
|
+
}
|
1679
|
+
|
1680
|
+
status = kern_proc_args_skip_argv(&kargs);
|
1681
|
+
if (status != SIGAR_OK) {
|
1682
|
+
sigar_kern_proc_args_destroy(&kargs);
|
1683
|
+
return status;
|
1684
|
+
}
|
1685
|
+
|
1686
|
+
count = kargs.count;
|
1687
|
+
ptr = kargs.ptr;
|
1688
|
+
end = kargs.end;
|
1689
|
+
|
1690
|
+
/* into environ */
|
1691
|
+
while (ptr < end) {
|
1692
|
+
char *val = strchr(ptr, '=');
|
1693
|
+
int klen, vlen, status;
|
1694
|
+
char key[256]; /* XXX is there a max key size? */
|
1695
|
+
|
1696
|
+
if (val == NULL) {
|
1697
|
+
/* not key=val format */
|
1698
|
+
break;
|
1699
|
+
}
|
1700
|
+
|
1701
|
+
klen = val - ptr;
|
1702
|
+
SIGAR_SSTRCPY(key, ptr);
|
1703
|
+
key[klen] = '\0';
|
1704
|
+
++val;
|
1705
|
+
|
1706
|
+
vlen = strlen(val);
|
1707
|
+
status = procenv->env_getter(procenv->data,
|
1708
|
+
key, klen, val, vlen);
|
1709
|
+
|
1710
|
+
if (status != SIGAR_OK) {
|
1711
|
+
/* not an error; just stop iterating */
|
1712
|
+
break;
|
1713
|
+
}
|
1714
|
+
|
1715
|
+
ptr += (klen + 1 + vlen + 1);
|
1716
|
+
|
1717
|
+
if (*ptr == '\0') {
|
1718
|
+
break;
|
1719
|
+
}
|
1720
|
+
}
|
1721
|
+
|
1722
|
+
sigar_kern_proc_args_destroy(&kargs);
|
1723
|
+
return SIGAR_OK;
|
1724
|
+
#else
|
1725
|
+
char **env;
|
1726
|
+
struct kinfo_proc *pinfo;
|
1727
|
+
int num;
|
1728
|
+
|
1729
|
+
if (!sigar->kmem) {
|
1730
|
+
return SIGAR_EPERM_KMEM;
|
1731
|
+
}
|
1732
|
+
|
1733
|
+
pinfo = kvm_getprocs(sigar->kmem, KERN_PROC_PID, pid, &num);
|
1734
|
+
if (!pinfo || (num < 1)) {
|
1735
|
+
return errno;
|
1736
|
+
}
|
1737
|
+
|
1738
|
+
if (!(env = kvm_getenvv(sigar->kmem, pinfo, 9086))) {
|
1739
|
+
return errno;
|
1740
|
+
}
|
1741
|
+
|
1742
|
+
while (*env) {
|
1743
|
+
char *ptr = *env++;
|
1744
|
+
char *val = strchr(ptr, '=');
|
1745
|
+
int klen, vlen, status;
|
1746
|
+
char key[128]; /* XXX is there a max key size? */
|
1747
|
+
|
1748
|
+
if (val == NULL) {
|
1749
|
+
/* not key=val format */
|
1750
|
+
procenv->env_getter(procenv->data, ptr, strlen(ptr), NULL, 0);
|
1751
|
+
break;
|
1752
|
+
}
|
1753
|
+
|
1754
|
+
klen = val - ptr;
|
1755
|
+
SIGAR_SSTRCPY(key, ptr);
|
1756
|
+
key[klen] = '\0';
|
1757
|
+
++val;
|
1758
|
+
|
1759
|
+
vlen = strlen(val);
|
1760
|
+
status = procenv->env_getter(procenv->data,
|
1761
|
+
key, klen, val, vlen);
|
1762
|
+
|
1763
|
+
if (status != SIGAR_OK) {
|
1764
|
+
/* not an error; just stop iterating */
|
1765
|
+
break;
|
1766
|
+
}
|
1767
|
+
|
1768
|
+
ptr += (klen + 1 + vlen + 1);
|
1769
|
+
}
|
1770
|
+
|
1771
|
+
return SIGAR_OK;
|
1772
|
+
#endif
|
1773
|
+
}
|
1774
|
+
|
1775
|
+
int sigar_proc_fd_get(sigar_t *sigar, sigar_pid_t pid,
|
1776
|
+
sigar_proc_fd_t *procfd)
|
1777
|
+
{
|
1778
|
+
#ifdef __FreeBSD__
|
1779
|
+
int status;
|
1780
|
+
bsd_pinfo_t *pinfo;
|
1781
|
+
struct filedesc filed;
|
1782
|
+
#if 0
|
1783
|
+
struct file **ofiles;
|
1784
|
+
int nfiles, i;
|
1785
|
+
size_t size;
|
1786
|
+
#endif
|
1787
|
+
if (!sigar->kmem) {
|
1788
|
+
return SIGAR_EPERM_KMEM;
|
1789
|
+
}
|
1790
|
+
|
1791
|
+
if ((status = sigar_get_pinfo(sigar, pid)) != SIGAR_OK) {
|
1792
|
+
return status;
|
1793
|
+
}
|
1794
|
+
pinfo = sigar->pinfo;
|
1795
|
+
|
1796
|
+
status = kread(sigar, &filed, sizeof(filed), (u_long)pinfo->KI_FD);
|
1797
|
+
if (status != SIGAR_OK) {
|
1798
|
+
return status;
|
1799
|
+
}
|
1800
|
+
#if 0
|
1801
|
+
nfiles = filed.fd_lastfile+1;
|
1802
|
+
size = sizeof(*ofiles) * nfiles;
|
1803
|
+
ofiles = malloc(size);
|
1804
|
+
status = kread(sigar, ofiles, size, (u_long)filed.fd_ofiles);
|
1805
|
+
if (status != SIGAR_OK) {
|
1806
|
+
free(ofiles);
|
1807
|
+
return status;
|
1808
|
+
}
|
1809
|
+
|
1810
|
+
procfd->total = 0;
|
1811
|
+
for (i=0; i<filed.fd_lastfile; i++) {
|
1812
|
+
if (!ofiles[i]) {
|
1813
|
+
continue;
|
1814
|
+
}
|
1815
|
+
procfd->total++;
|
1816
|
+
}
|
1817
|
+
|
1818
|
+
free(ofiles);
|
1819
|
+
#else
|
1820
|
+
/* seems the same as the above */
|
1821
|
+
procfd->total = filed.fd_lastfile;
|
1822
|
+
#endif
|
1823
|
+
|
1824
|
+
return SIGAR_OK;
|
1825
|
+
#else
|
1826
|
+
return SIGAR_ENOTIMPL;
|
1827
|
+
#endif
|
1828
|
+
}
|
1829
|
+
|
1830
|
+
int sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid,
|
1831
|
+
sigar_proc_exe_t *procexe)
|
1832
|
+
{
|
1833
|
+
#ifdef DARWIN
|
1834
|
+
int status;
|
1835
|
+
sigar_kern_proc_args_t kargs;
|
1836
|
+
|
1837
|
+
status = sigar_kern_proc_args_get(sigar, pid, procexe->name, &kargs);
|
1838
|
+
if (status != SIGAR_OK) {
|
1839
|
+
return status;
|
1840
|
+
}
|
1841
|
+
|
1842
|
+
procexe->cwd[0] = '\0';
|
1843
|
+
procexe->root[0] = '\0';
|
1844
|
+
|
1845
|
+
/* attempt to determine cwd from $PWD */
|
1846
|
+
status = kern_proc_args_skip_argv(&kargs);
|
1847
|
+
if (status == SIGAR_OK) {
|
1848
|
+
char *ptr = kargs.ptr;
|
1849
|
+
char *end = kargs.end;
|
1850
|
+
|
1851
|
+
/* into environ */
|
1852
|
+
while (ptr < end) {
|
1853
|
+
int len = strlen(ptr);
|
1854
|
+
|
1855
|
+
if ((len > 4) &&
|
1856
|
+
(ptr[0] == 'P') &&
|
1857
|
+
(ptr[1] == 'W') &&
|
1858
|
+
(ptr[2] == 'D') &&
|
1859
|
+
(ptr[3] == '='))
|
1860
|
+
{
|
1861
|
+
memcpy(procexe->cwd, ptr+4, len-3);
|
1862
|
+
break;
|
1863
|
+
}
|
1864
|
+
|
1865
|
+
ptr += len+1;
|
1866
|
+
}
|
1867
|
+
}
|
1868
|
+
|
1869
|
+
sigar_kern_proc_args_destroy(&kargs);
|
1870
|
+
|
1871
|
+
return SIGAR_OK;
|
1872
|
+
#else
|
1873
|
+
int len;
|
1874
|
+
char name[1024];
|
1875
|
+
|
1876
|
+
procexe->cwd[0] = '\0';
|
1877
|
+
procexe->root[0] = '\0';
|
1878
|
+
|
1879
|
+
(void)SIGAR_PROC_FILENAME(name, pid, "/file");
|
1880
|
+
|
1881
|
+
if ((len = readlink(name, procexe->name,
|
1882
|
+
sizeof(procexe->name)-1)) < 0)
|
1883
|
+
{
|
1884
|
+
return PROCFS_STATUS(errno);
|
1885
|
+
}
|
1886
|
+
|
1887
|
+
procexe->name[len] = '\0';
|
1888
|
+
|
1889
|
+
return SIGAR_OK;
|
1890
|
+
#endif
|
1891
|
+
}
|
1892
|
+
|
1893
|
+
#ifdef DARWIN
|
1894
|
+
static int sigar_dlinfo_modules(sigar_t *sigar, sigar_proc_modules_t *procmods)
|
1895
|
+
{
|
1896
|
+
uint32_t i, count = _dyld_image_count();
|
1897
|
+
|
1898
|
+
for (i=0; i<count; i++) {
|
1899
|
+
int status;
|
1900
|
+
const char *name =
|
1901
|
+
_dyld_get_image_name(i);
|
1902
|
+
|
1903
|
+
if (name == NULL) {
|
1904
|
+
continue;
|
1905
|
+
}
|
1906
|
+
status =
|
1907
|
+
procmods->module_getter(procmods->data,
|
1908
|
+
(char *)name, strlen(name));
|
1909
|
+
|
1910
|
+
if (status != SIGAR_OK) {
|
1911
|
+
/* not an error; just stop iterating */
|
1912
|
+
break;
|
1913
|
+
}
|
1914
|
+
}
|
1915
|
+
return SIGAR_OK;
|
1916
|
+
}
|
1917
|
+
#endif /* DARWIN */
|
1918
|
+
|
1919
|
+
int sigar_proc_modules_get(sigar_t *sigar, sigar_pid_t pid,
|
1920
|
+
sigar_proc_modules_t *procmods)
|
1921
|
+
{
|
1922
|
+
#if defined(SIGAR_HAS_DLINFO_MODULES) || defined(DARWIN)
|
1923
|
+
if (pid == sigar_pid_get(sigar)) {
|
1924
|
+
return sigar_dlinfo_modules(sigar, procmods);
|
1925
|
+
}
|
1926
|
+
#endif
|
1927
|
+
return SIGAR_ENOTIMPL;
|
1928
|
+
}
|
1929
|
+
|
1930
|
+
#define SIGAR_MICROSEC2NANO(s) \
|
1931
|
+
((sigar_uint64_t)(s) * (sigar_uint64_t)1000)
|
1932
|
+
|
1933
|
+
#define TIME_NSEC(t) \
|
1934
|
+
(SIGAR_SEC2NANO((t).tv_sec) + SIGAR_MICROSEC2NANO((t).tv_usec))
|
1935
|
+
|
1936
|
+
int sigar_thread_cpu_get(sigar_t *sigar,
|
1937
|
+
sigar_uint64_t id,
|
1938
|
+
sigar_thread_cpu_t *cpu)
|
1939
|
+
{
|
1940
|
+
#if defined(DARWIN)
|
1941
|
+
mach_port_t self = mach_thread_self();
|
1942
|
+
thread_basic_info_data_t info;
|
1943
|
+
mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
|
1944
|
+
kern_return_t status;
|
1945
|
+
|
1946
|
+
status = thread_info(self, THREAD_BASIC_INFO,
|
1947
|
+
(thread_info_t)&info, &count);
|
1948
|
+
if (status != KERN_SUCCESS) {
|
1949
|
+
return errno;
|
1950
|
+
}
|
1951
|
+
|
1952
|
+
mach_port_deallocate(mach_task_self(), self);
|
1953
|
+
|
1954
|
+
cpu->user = tval2nsec(info.user_time);
|
1955
|
+
cpu->sys = tval2nsec(info.system_time);
|
1956
|
+
cpu->total = cpu->user + cpu->sys;
|
1957
|
+
#elif defined(__NetBSD__)
|
1958
|
+
return SIGAR_ENOTIMPL; /* http://tinyurl.com/chbvln */
|
1959
|
+
#else
|
1960
|
+
/* XXX this is not per-thread, it is for the whole-process.
|
1961
|
+
* just want to use for the shell time command at the moment.
|
1962
|
+
*/
|
1963
|
+
struct rusage usage;
|
1964
|
+
getrusage(RUSAGE_SELF, &usage);
|
1965
|
+
|
1966
|
+
cpu->user = TIME_NSEC(usage.ru_utime);
|
1967
|
+
cpu->sys = TIME_NSEC(usage.ru_stime);
|
1968
|
+
cpu->total = TIME_NSEC(usage.ru_utime) + TIME_NSEC(usage.ru_stime);
|
1969
|
+
#endif
|
1970
|
+
|
1971
|
+
return SIGAR_OK;
|
1972
|
+
}
|
1973
|
+
|
1974
|
+
int sigar_os_fs_type_get(sigar_file_system_t *fsp)
|
1975
|
+
{
|
1976
|
+
char *type = fsp->sys_type_name;
|
1977
|
+
|
1978
|
+
/* see sys/disklabel.h */
|
1979
|
+
switch (*type) {
|
1980
|
+
case 'f':
|
1981
|
+
if (strEQ(type, "ffs")) {
|
1982
|
+
fsp->type = SIGAR_FSTYPE_LOCAL_DISK;
|
1983
|
+
}
|
1984
|
+
break;
|
1985
|
+
case 'h':
|
1986
|
+
if (strEQ(type, "hfs")) {
|
1987
|
+
fsp->type = SIGAR_FSTYPE_LOCAL_DISK;
|
1988
|
+
}
|
1989
|
+
break;
|
1990
|
+
case 'u':
|
1991
|
+
if (strEQ(type, "ufs")) {
|
1992
|
+
fsp->type = SIGAR_FSTYPE_LOCAL_DISK;
|
1993
|
+
}
|
1994
|
+
break;
|
1995
|
+
}
|
1996
|
+
|
1997
|
+
return fsp->type;
|
1998
|
+
}
|
1999
|
+
|
2000
|
+
static void get_fs_options(char *opts, int osize, long flags)
|
2001
|
+
{
|
2002
|
+
*opts = '\0';
|
2003
|
+
if (flags & MNT_RDONLY) strncat(opts, "ro", osize);
|
2004
|
+
else strncat(opts, "rw", osize);
|
2005
|
+
if (flags & MNT_SYNCHRONOUS) strncat(opts, ",sync", osize);
|
2006
|
+
if (flags & MNT_NOEXEC) strncat(opts, ",noexec", osize);
|
2007
|
+
if (flags & MNT_NOSUID) strncat(opts, ",nosuid", osize);
|
2008
|
+
#ifdef MNT_NODEV
|
2009
|
+
if (flags & MNT_NODEV) strncat(opts, ",nodev", osize);
|
2010
|
+
#endif
|
2011
|
+
#ifdef MNT_UNION
|
2012
|
+
if (flags & MNT_UNION) strncat(opts, ",union", osize);
|
2013
|
+
#endif
|
2014
|
+
if (flags & MNT_ASYNC) strncat(opts, ",async", osize);
|
2015
|
+
#ifdef MNT_NOATIME
|
2016
|
+
if (flags & MNT_NOATIME) strncat(opts, ",noatime", osize);
|
2017
|
+
#endif
|
2018
|
+
#ifdef MNT_NOCLUSTERR
|
2019
|
+
if (flags & MNT_NOCLUSTERR) strncat(opts, ",noclusterr", osize);
|
2020
|
+
#endif
|
2021
|
+
#ifdef MNT_NOCLUSTERW
|
2022
|
+
if (flags & MNT_NOCLUSTERW) strncat(opts, ",noclusterw", osize);
|
2023
|
+
#endif
|
2024
|
+
#ifdef MNT_NOSYMFOLLOW
|
2025
|
+
if (flags & MNT_NOSYMFOLLOW) strncat(opts, ",nosymfollow", osize);
|
2026
|
+
#endif
|
2027
|
+
#ifdef MNT_SUIDDIR
|
2028
|
+
if (flags & MNT_SUIDDIR) strncat(opts, ",suiddir", osize);
|
2029
|
+
#endif
|
2030
|
+
#ifdef MNT_SOFTDEP
|
2031
|
+
if (flags & MNT_SOFTDEP) strncat(opts, ",soft-updates", osize);
|
2032
|
+
#endif
|
2033
|
+
if (flags & MNT_LOCAL) strncat(opts, ",local", osize);
|
2034
|
+
if (flags & MNT_QUOTA) strncat(opts, ",quota", osize);
|
2035
|
+
if (flags & MNT_ROOTFS) strncat(opts, ",rootfs", osize);
|
2036
|
+
#ifdef MNT_USER
|
2037
|
+
if (flags & MNT_USER) strncat(opts, ",user", osize);
|
2038
|
+
#endif
|
2039
|
+
#ifdef MNT_IGNORE
|
2040
|
+
if (flags & MNT_IGNORE) strncat(opts, ",ignore", osize);
|
2041
|
+
#endif
|
2042
|
+
if (flags & MNT_EXPORTED) strncat(opts, ",nfs", osize);
|
2043
|
+
}
|
2044
|
+
|
2045
|
+
#ifdef __NetBSD__
|
2046
|
+
#define sigar_statfs statvfs
|
2047
|
+
#define sigar_getfsstat getvfsstat
|
2048
|
+
#define sigar_f_flags f_flag
|
2049
|
+
#else
|
2050
|
+
#define sigar_statfs statfs
|
2051
|
+
#define sigar_getfsstat getfsstat
|
2052
|
+
#define sigar_f_flags f_flags
|
2053
|
+
#endif
|
2054
|
+
|
2055
|
+
int sigar_file_system_list_get(sigar_t *sigar,
|
2056
|
+
sigar_file_system_list_t *fslist)
|
2057
|
+
{
|
2058
|
+
struct sigar_statfs *fs;
|
2059
|
+
int num, i;
|
2060
|
+
int is_debug = SIGAR_LOG_IS_DEBUG(sigar);
|
2061
|
+
long len;
|
2062
|
+
|
2063
|
+
if ((num = sigar_getfsstat(NULL, 0, MNT_NOWAIT)) < 0) {
|
2064
|
+
return errno;
|
2065
|
+
}
|
2066
|
+
|
2067
|
+
len = sizeof(*fs) * num;
|
2068
|
+
fs = malloc(len);
|
2069
|
+
|
2070
|
+
if ((num = sigar_getfsstat(fs, len, MNT_NOWAIT)) < 0) {
|
2071
|
+
free(fs);
|
2072
|
+
return errno;
|
2073
|
+
}
|
2074
|
+
|
2075
|
+
sigar_file_system_list_create(fslist);
|
2076
|
+
|
2077
|
+
for (i=0; i<num; i++) {
|
2078
|
+
sigar_file_system_t *fsp;
|
2079
|
+
|
2080
|
+
#ifdef MNT_AUTOMOUNTED
|
2081
|
+
if (fs[i].sigar_f_flags & MNT_AUTOMOUNTED) {
|
2082
|
+
if (is_debug) {
|
2083
|
+
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
|
2084
|
+
"[file_system_list] skipping automounted %s: %s",
|
2085
|
+
fs[i].f_fstypename, fs[i].f_mntonname);
|
2086
|
+
}
|
2087
|
+
continue;
|
2088
|
+
}
|
2089
|
+
#endif
|
2090
|
+
|
2091
|
+
#ifdef MNT_RDONLY
|
2092
|
+
if (fs[i].sigar_f_flags & MNT_RDONLY) {
|
2093
|
+
/* e.g. ftp mount or .dmg image */
|
2094
|
+
if (is_debug) {
|
2095
|
+
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
|
2096
|
+
"[file_system_list] skipping readonly %s: %s",
|
2097
|
+
fs[i].f_fstypename, fs[i].f_mntonname);
|
2098
|
+
}
|
2099
|
+
continue;
|
2100
|
+
}
|
2101
|
+
#endif
|
2102
|
+
|
2103
|
+
SIGAR_FILE_SYSTEM_LIST_GROW(fslist);
|
2104
|
+
|
2105
|
+
fsp = &fslist->data[fslist->number++];
|
2106
|
+
|
2107
|
+
SIGAR_SSTRCPY(fsp->dir_name, fs[i].f_mntonname);
|
2108
|
+
SIGAR_SSTRCPY(fsp->dev_name, fs[i].f_mntfromname);
|
2109
|
+
SIGAR_SSTRCPY(fsp->sys_type_name, fs[i].f_fstypename);
|
2110
|
+
get_fs_options(fsp->options, sizeof(fsp->options)-1, fs[i].sigar_f_flags);
|
2111
|
+
|
2112
|
+
sigar_fs_type_init(fsp);
|
2113
|
+
}
|
2114
|
+
|
2115
|
+
free(fs);
|
2116
|
+
return SIGAR_OK;
|
2117
|
+
}
|
2118
|
+
|
2119
|
+
#ifdef DARWIN
|
2120
|
+
#define IoStatGetValue(key, val) \
|
2121
|
+
if ((number = (CFNumberRef)CFDictionaryGetValue(stats, CFSTR(kIOBlockStorageDriverStatistics##key)))) \
|
2122
|
+
CFNumberGetValue(number, kCFNumberSInt64Type, &val)
|
2123
|
+
#endif
|
2124
|
+
|
2125
|
+
int sigar_disk_usage_get(sigar_t *sigar, const char *name,
|
2126
|
+
sigar_disk_usage_t *disk)
|
2127
|
+
{
|
2128
|
+
#if defined(DARWIN)
|
2129
|
+
kern_return_t status;
|
2130
|
+
io_registry_entry_t parent;
|
2131
|
+
io_service_t service;
|
2132
|
+
CFDictionaryRef props;
|
2133
|
+
CFNumberRef number;
|
2134
|
+
sigar_iodev_t *iodev = sigar_iodev_get(sigar, name);
|
2135
|
+
char dname[256], *ptr;
|
2136
|
+
|
2137
|
+
SIGAR_DISK_STATS_INIT(disk);
|
2138
|
+
|
2139
|
+
if (!iodev) {
|
2140
|
+
return ENXIO;
|
2141
|
+
}
|
2142
|
+
|
2143
|
+
/* "/dev/disk0s1" -> "disk0" */ /* XXX better way? */
|
2144
|
+
ptr = &iodev->name[SSTRLEN(SIGAR_DEV_PREFIX)];
|
2145
|
+
SIGAR_SSTRCPY(dname, ptr);
|
2146
|
+
ptr = dname;
|
2147
|
+
if (strnEQ(ptr, "disk", 4)) {
|
2148
|
+
ptr += 4;
|
2149
|
+
if ((ptr = strchr(ptr, 's')) && isdigit(*(ptr+1))) {
|
2150
|
+
*ptr = '\0';
|
2151
|
+
}
|
2152
|
+
}
|
2153
|
+
|
2154
|
+
if (SIGAR_LOG_IS_DEBUG(sigar)) {
|
2155
|
+
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
|
2156
|
+
"[disk_usage] map %s -> %s",
|
2157
|
+
iodev->name, dname);
|
2158
|
+
}
|
2159
|
+
|
2160
|
+
/* e.g. name == "disk0" */
|
2161
|
+
service = IOServiceGetMatchingService(kIOMasterPortDefault,
|
2162
|
+
IOBSDNameMatching(kIOMasterPortDefault, 0, dname));
|
2163
|
+
|
2164
|
+
if (!service) {
|
2165
|
+
return errno;
|
2166
|
+
}
|
2167
|
+
|
2168
|
+
status = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent);
|
2169
|
+
if (status != KERN_SUCCESS) {
|
2170
|
+
IOObjectRelease(service);
|
2171
|
+
return status;
|
2172
|
+
}
|
2173
|
+
|
2174
|
+
status = IORegistryEntryCreateCFProperties(parent,
|
2175
|
+
(CFMutableDictionaryRef *)&props,
|
2176
|
+
kCFAllocatorDefault,
|
2177
|
+
kNilOptions);
|
2178
|
+
if (props) {
|
2179
|
+
CFDictionaryRef stats =
|
2180
|
+
(CFDictionaryRef)CFDictionaryGetValue(props,
|
2181
|
+
CFSTR(kIOBlockStorageDriverStatisticsKey));
|
2182
|
+
|
2183
|
+
if (stats) {
|
2184
|
+
IoStatGetValue(ReadsKey, disk->reads);
|
2185
|
+
IoStatGetValue(BytesReadKey, disk->read_bytes);
|
2186
|
+
IoStatGetValue(TotalReadTimeKey, disk->rtime);
|
2187
|
+
IoStatGetValue(WritesKey, disk->writes);
|
2188
|
+
IoStatGetValue(BytesWrittenKey, disk->write_bytes);
|
2189
|
+
IoStatGetValue(TotalWriteTimeKey, disk->wtime);
|
2190
|
+
disk->time = disk->rtime + disk->wtime;
|
2191
|
+
}
|
2192
|
+
|
2193
|
+
CFRelease(props);
|
2194
|
+
}
|
2195
|
+
|
2196
|
+
IOObjectRelease(service);
|
2197
|
+
IOObjectRelease(parent);
|
2198
|
+
|
2199
|
+
return SIGAR_OK;
|
2200
|
+
#elif defined(__FreeBSD__)
|
2201
|
+
/* XXX incomplete */
|
2202
|
+
struct sigar_statfs buf;
|
2203
|
+
|
2204
|
+
if (sigar_statfs(name, &buf) < 0) {
|
2205
|
+
return errno;
|
2206
|
+
}
|
2207
|
+
|
2208
|
+
SIGAR_DISK_STATS_INIT(disk);
|
2209
|
+
|
2210
|
+
disk->reads = buf.f_syncreads + buf.f_asyncreads;
|
2211
|
+
disk->writes = buf.f_syncwrites + buf.f_asyncwrites;
|
2212
|
+
return SIGAR_OK;
|
2213
|
+
#else
|
2214
|
+
SIGAR_DISK_STATS_INIT(disk);
|
2215
|
+
return SIGAR_ENOTIMPL;
|
2216
|
+
#endif
|
2217
|
+
}
|
2218
|
+
|
2219
|
+
int sigar_file_system_usage_get(sigar_t *sigar,
|
2220
|
+
const char *dirname,
|
2221
|
+
sigar_file_system_usage_t *fsusage)
|
2222
|
+
{
|
2223
|
+
int status = sigar_statvfs(sigar, dirname, fsusage);
|
2224
|
+
|
2225
|
+
if (status != SIGAR_OK) {
|
2226
|
+
return status;
|
2227
|
+
}
|
2228
|
+
|
2229
|
+
fsusage->use_percent = sigar_file_system_usage_calc_used(sigar, fsusage);
|
2230
|
+
|
2231
|
+
sigar_disk_usage_get(sigar, dirname, &fsusage->disk);
|
2232
|
+
|
2233
|
+
return SIGAR_OK;
|
2234
|
+
}
|
2235
|
+
|
2236
|
+
#ifdef DARWIN
|
2237
|
+
#define CTL_HW_FREQ "hw.cpufrequency"
|
2238
|
+
#else
|
2239
|
+
/* XXX FreeBSD 5.x+ only? */
|
2240
|
+
#define CTL_HW_FREQ "machdep.tsc_freq"
|
2241
|
+
#endif
|
2242
|
+
|
2243
|
+
int sigar_cpu_info_list_get(sigar_t *sigar,
|
2244
|
+
sigar_cpu_info_list_t *cpu_infos)
|
2245
|
+
{
|
2246
|
+
int i;
|
2247
|
+
unsigned int mhz;
|
2248
|
+
int cache_size=SIGAR_FIELD_NOTIMPL;
|
2249
|
+
size_t size;
|
2250
|
+
char model[128], vendor[128], *ptr;
|
2251
|
+
|
2252
|
+
size = sizeof(mhz);
|
2253
|
+
|
2254
|
+
(void)sigar_cpu_core_count(sigar);
|
2255
|
+
|
2256
|
+
#if defined(DARWIN)
|
2257
|
+
{
|
2258
|
+
int mib[] = { CTL_HW, HW_CPU_FREQ };
|
2259
|
+
size = sizeof(mhz);
|
2260
|
+
if (sysctl(mib, NMIB(mib), &mhz, &size, NULL, 0) < 0) {
|
2261
|
+
mhz = SIGAR_FIELD_NOTIMPL;
|
2262
|
+
}
|
2263
|
+
}
|
2264
|
+
#elif defined(__FreeBSD__)
|
2265
|
+
if (sysctlbyname(CTL_HW_FREQ, &mhz, &size, NULL, 0) < 0) {
|
2266
|
+
mhz = SIGAR_FIELD_NOTIMPL;
|
2267
|
+
}
|
2268
|
+
#else
|
2269
|
+
/*XXX OpenBSD*/
|
2270
|
+
mhz = SIGAR_FIELD_NOTIMPL;
|
2271
|
+
#endif
|
2272
|
+
|
2273
|
+
if (mhz != SIGAR_FIELD_NOTIMPL) {
|
2274
|
+
mhz /= 1000000;
|
2275
|
+
}
|
2276
|
+
|
2277
|
+
size = sizeof(model);
|
2278
|
+
#ifdef __OpenBSD__
|
2279
|
+
if (1) {
|
2280
|
+
#else
|
2281
|
+
if (sysctlbyname("hw.model", &model, &size, NULL, 0) < 0) {
|
2282
|
+
#endif
|
2283
|
+
int mib[] = { CTL_HW, HW_MODEL };
|
2284
|
+
size = sizeof(model);
|
2285
|
+
if (sysctl(mib, NMIB(mib), &model[0], &size, NULL, 0) < 0) {
|
2286
|
+
#ifdef DARWIN
|
2287
|
+
strcpy(model, "powerpc");
|
2288
|
+
#else
|
2289
|
+
strcpy(model, "Unknown");
|
2290
|
+
#endif
|
2291
|
+
}
|
2292
|
+
}
|
2293
|
+
|
2294
|
+
if (mhz == SIGAR_FIELD_NOTIMPL) {
|
2295
|
+
/* freebsd4 */
|
2296
|
+
mhz = sigar_cpu_mhz_from_model(model);
|
2297
|
+
}
|
2298
|
+
|
2299
|
+
#ifdef DARWIN
|
2300
|
+
size = sizeof(vendor);
|
2301
|
+
if (sysctlbyname("machdep.cpu.vendor", &vendor, &size, NULL, 0) < 0) {
|
2302
|
+
SIGAR_SSTRCPY(vendor, "Apple");
|
2303
|
+
}
|
2304
|
+
else {
|
2305
|
+
/* GenuineIntel -> Intel */
|
2306
|
+
if (strstr(vendor, "Intel")) {
|
2307
|
+
SIGAR_SSTRCPY(vendor, "Intel");
|
2308
|
+
}
|
2309
|
+
}
|
2310
|
+
#endif
|
2311
|
+
|
2312
|
+
if ((ptr = strchr(model, ' '))) {
|
2313
|
+
if (strstr(model, "Intel")) {
|
2314
|
+
SIGAR_SSTRCPY(vendor, "Intel");
|
2315
|
+
}
|
2316
|
+
else if (strstr(model, "AMD")) {
|
2317
|
+
SIGAR_SSTRCPY(vendor, "AMD");
|
2318
|
+
}
|
2319
|
+
else {
|
2320
|
+
SIGAR_SSTRCPY(vendor, "Unknown");
|
2321
|
+
}
|
2322
|
+
SIGAR_SSTRCPY(model, ptr+1);
|
2323
|
+
}
|
2324
|
+
|
2325
|
+
#ifdef DARWIN
|
2326
|
+
{
|
2327
|
+
int mib[] = { CTL_HW, HW_L2CACHESIZE }; /* in bytes */
|
2328
|
+
size = sizeof(cache_size);
|
2329
|
+
if (sysctl(mib, NMIB(mib), &cache_size, &size, NULL, 0) < 0) {
|
2330
|
+
cache_size = SIGAR_FIELD_NOTIMPL;
|
2331
|
+
}
|
2332
|
+
else {
|
2333
|
+
cache_size /= 1024; /* convert to KB */
|
2334
|
+
}
|
2335
|
+
}
|
2336
|
+
#endif
|
2337
|
+
|
2338
|
+
sigar_cpu_info_list_create(cpu_infos);
|
2339
|
+
|
2340
|
+
for (i=0; i<sigar->ncpu; i++) {
|
2341
|
+
sigar_cpu_info_t *info;
|
2342
|
+
|
2343
|
+
SIGAR_CPU_INFO_LIST_GROW(cpu_infos);
|
2344
|
+
|
2345
|
+
info = &cpu_infos->data[cpu_infos->number++];
|
2346
|
+
|
2347
|
+
SIGAR_SSTRCPY(info->vendor, vendor);
|
2348
|
+
SIGAR_SSTRCPY(info->model, model);
|
2349
|
+
sigar_cpu_model_adjust(sigar, info);
|
2350
|
+
|
2351
|
+
info->mhz = mhz;
|
2352
|
+
info->cache_size = cache_size;
|
2353
|
+
info->total_cores = sigar->ncpu;
|
2354
|
+
info->cores_per_socket = sigar->lcpu;
|
2355
|
+
info->total_sockets = sigar_cpu_socket_count(sigar);
|
2356
|
+
}
|
2357
|
+
|
2358
|
+
return SIGAR_OK;
|
2359
|
+
}
|
2360
|
+
|
2361
|
+
#define rt_s_addr(sa) ((struct sockaddr_in *)(sa))->sin_addr.s_addr
|
2362
|
+
|
2363
|
+
#ifndef SA_SIZE
|
2364
|
+
#define SA_SIZE(sa) \
|
2365
|
+
( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \
|
2366
|
+
sizeof(long) : \
|
2367
|
+
1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
|
2368
|
+
#endif
|
2369
|
+
|
2370
|
+
int sigar_net_route_list_get(sigar_t *sigar,
|
2371
|
+
sigar_net_route_list_t *routelist)
|
2372
|
+
{
|
2373
|
+
size_t needed;
|
2374
|
+
int bit;
|
2375
|
+
char *buf, *next, *lim;
|
2376
|
+
struct rt_msghdr *rtm;
|
2377
|
+
int mib[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_DUMP, 0 };
|
2378
|
+
|
2379
|
+
if (sysctl(mib, NMIB(mib), NULL, &needed, NULL, 0) < 0) {
|
2380
|
+
return errno;
|
2381
|
+
}
|
2382
|
+
|
2383
|
+
buf = malloc(needed);
|
2384
|
+
|
2385
|
+
if (sysctl(mib, NMIB(mib), buf, &needed, NULL, 0) < 0) {
|
2386
|
+
free(buf);
|
2387
|
+
return errno;
|
2388
|
+
}
|
2389
|
+
|
2390
|
+
sigar_net_route_list_create(routelist);
|
2391
|
+
|
2392
|
+
lim = buf + needed;
|
2393
|
+
for (next = buf; next < lim; next += rtm->rtm_msglen) {
|
2394
|
+
struct sockaddr *sa;
|
2395
|
+
sigar_net_route_t *route;
|
2396
|
+
rtm = (struct rt_msghdr *)next;
|
2397
|
+
|
2398
|
+
if (rtm->rtm_type != RTM_GET) {
|
2399
|
+
continue;
|
2400
|
+
}
|
2401
|
+
|
2402
|
+
sa = (struct sockaddr *)(rtm + 1);
|
2403
|
+
|
2404
|
+
if (sa->sa_family != AF_INET) {
|
2405
|
+
continue;
|
2406
|
+
}
|
2407
|
+
|
2408
|
+
SIGAR_NET_ROUTE_LIST_GROW(routelist);
|
2409
|
+
route = &routelist->data[routelist->number++];
|
2410
|
+
SIGAR_ZERO(route);
|
2411
|
+
|
2412
|
+
route->flags = rtm->rtm_flags;
|
2413
|
+
|
2414
|
+
for (bit=RTA_DST;
|
2415
|
+
bit && ((char *)sa < lim);
|
2416
|
+
bit <<= 1)
|
2417
|
+
{
|
2418
|
+
if ((rtm->rtm_addrs & bit) == 0) {
|
2419
|
+
continue;
|
2420
|
+
}
|
2421
|
+
switch (bit) {
|
2422
|
+
case RTA_DST:
|
2423
|
+
sigar_net_address_set(route->destination,
|
2424
|
+
rt_s_addr(sa));
|
2425
|
+
break;
|
2426
|
+
case RTA_GATEWAY:
|
2427
|
+
if (sa->sa_family == AF_INET) {
|
2428
|
+
sigar_net_address_set(route->gateway,
|
2429
|
+
rt_s_addr(sa));
|
2430
|
+
}
|
2431
|
+
break;
|
2432
|
+
case RTA_NETMASK:
|
2433
|
+
sigar_net_address_set(route->mask,
|
2434
|
+
rt_s_addr(sa));
|
2435
|
+
break;
|
2436
|
+
case RTA_IFA:
|
2437
|
+
break;
|
2438
|
+
}
|
2439
|
+
|
2440
|
+
sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa));
|
2441
|
+
}
|
2442
|
+
}
|
2443
|
+
|
2444
|
+
free(buf);
|
2445
|
+
|
2446
|
+
return SIGAR_OK;
|
2447
|
+
}
|
2448
|
+
|
2449
|
+
typedef enum {
|
2450
|
+
IFMSG_ITER_LIST,
|
2451
|
+
IFMSG_ITER_GET
|
2452
|
+
} ifmsg_iter_e;
|
2453
|
+
|
2454
|
+
typedef struct {
|
2455
|
+
const char *name;
|
2456
|
+
ifmsg_iter_e type;
|
2457
|
+
union {
|
2458
|
+
sigar_net_interface_list_t *iflist;
|
2459
|
+
struct if_msghdr *ifm;
|
2460
|
+
} data;
|
2461
|
+
} ifmsg_iter_t;
|
2462
|
+
|
2463
|
+
static int sigar_ifmsg_init(sigar_t *sigar)
|
2464
|
+
{
|
2465
|
+
int mib[] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_IFLIST, 0 };
|
2466
|
+
size_t len;
|
2467
|
+
|
2468
|
+
if (sysctl(mib, NMIB(mib), NULL, &len, NULL, 0) < 0) {
|
2469
|
+
return errno;
|
2470
|
+
}
|
2471
|
+
|
2472
|
+
if (sigar->ifconf_len < len) {
|
2473
|
+
sigar->ifconf_buf = realloc(sigar->ifconf_buf, len);
|
2474
|
+
sigar->ifconf_len = len;
|
2475
|
+
}
|
2476
|
+
|
2477
|
+
if (sysctl(mib, NMIB(mib), sigar->ifconf_buf, &len, NULL, 0) < 0) {
|
2478
|
+
return errno;
|
2479
|
+
}
|
2480
|
+
|
2481
|
+
return SIGAR_OK;
|
2482
|
+
}
|
2483
|
+
|
2484
|
+
static int has_ifaddr(char *name)
|
2485
|
+
{
|
2486
|
+
int sock, status;
|
2487
|
+
struct ifreq ifr;
|
2488
|
+
|
2489
|
+
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
2490
|
+
return errno;
|
2491
|
+
}
|
2492
|
+
SIGAR_SSTRCPY(ifr.ifr_name, name);
|
2493
|
+
if (ioctl(sock, SIOCGIFADDR, &ifr) == 0) {
|
2494
|
+
status = SIGAR_OK;
|
2495
|
+
}
|
2496
|
+
else {
|
2497
|
+
status = errno;
|
2498
|
+
}
|
2499
|
+
|
2500
|
+
close(sock);
|
2501
|
+
return status;
|
2502
|
+
}
|
2503
|
+
|
2504
|
+
static int sigar_ifmsg_iter(sigar_t *sigar, ifmsg_iter_t *iter)
|
2505
|
+
{
|
2506
|
+
char *end = sigar->ifconf_buf + sigar->ifconf_len;
|
2507
|
+
char *ptr = sigar->ifconf_buf;
|
2508
|
+
|
2509
|
+
if (iter->type == IFMSG_ITER_LIST) {
|
2510
|
+
sigar_net_interface_list_create(iter->data.iflist);
|
2511
|
+
}
|
2512
|
+
|
2513
|
+
while (ptr < end) {
|
2514
|
+
char *name;
|
2515
|
+
struct sockaddr_dl *sdl;
|
2516
|
+
struct if_msghdr *ifm = (struct if_msghdr *)ptr;
|
2517
|
+
|
2518
|
+
if (ifm->ifm_type != RTM_IFINFO) {
|
2519
|
+
break;
|
2520
|
+
}
|
2521
|
+
|
2522
|
+
ptr += ifm->ifm_msglen;
|
2523
|
+
|
2524
|
+
while (ptr < end) {
|
2525
|
+
struct if_msghdr *next = (struct if_msghdr *)ptr;
|
2526
|
+
|
2527
|
+
if (next->ifm_type != RTM_NEWADDR) {
|
2528
|
+
break;
|
2529
|
+
}
|
2530
|
+
|
2531
|
+
ptr += next->ifm_msglen;
|
2532
|
+
}
|
2533
|
+
|
2534
|
+
sdl = (struct sockaddr_dl *)(ifm + 1);
|
2535
|
+
if (sdl->sdl_family != AF_LINK) {
|
2536
|
+
continue;
|
2537
|
+
}
|
2538
|
+
|
2539
|
+
switch (iter->type) {
|
2540
|
+
case IFMSG_ITER_LIST:
|
2541
|
+
if (sdl->sdl_type == IFT_OTHER) {
|
2542
|
+
if (has_ifaddr(sdl->sdl_data) != SIGAR_OK) {
|
2543
|
+
break;
|
2544
|
+
}
|
2545
|
+
}
|
2546
|
+
else if (!((sdl->sdl_type == IFT_ETHER) ||
|
2547
|
+
(sdl->sdl_type == IFT_LOOP)))
|
2548
|
+
{
|
2549
|
+
break; /* XXX deal w/ other weirdo interfaces */
|
2550
|
+
}
|
2551
|
+
|
2552
|
+
SIGAR_NET_IFLIST_GROW(iter->data.iflist);
|
2553
|
+
|
2554
|
+
/* sdl_data doesn't include a trailing \0, it is only sdl_nlen long */
|
2555
|
+
name = malloc(sdl->sdl_nlen+1);
|
2556
|
+
memcpy(name, sdl->sdl_data, sdl->sdl_nlen);
|
2557
|
+
name[sdl->sdl_nlen] = '\0'; /* add the missing \0 */
|
2558
|
+
|
2559
|
+
iter->data.iflist->data[iter->data.iflist->number++] = name;
|
2560
|
+
break;
|
2561
|
+
|
2562
|
+
case IFMSG_ITER_GET:
|
2563
|
+
if (strEQ(iter->name, sdl->sdl_data)) {
|
2564
|
+
iter->data.ifm = ifm;
|
2565
|
+
return SIGAR_OK;
|
2566
|
+
}
|
2567
|
+
}
|
2568
|
+
}
|
2569
|
+
|
2570
|
+
switch (iter->type) {
|
2571
|
+
case IFMSG_ITER_LIST:
|
2572
|
+
return SIGAR_OK;
|
2573
|
+
|
2574
|
+
case IFMSG_ITER_GET:
|
2575
|
+
default:
|
2576
|
+
return ENXIO;
|
2577
|
+
}
|
2578
|
+
}
|
2579
|
+
|
2580
|
+
int sigar_net_interface_list_get(sigar_t *sigar,
|
2581
|
+
sigar_net_interface_list_t *iflist)
|
2582
|
+
{
|
2583
|
+
int status;
|
2584
|
+
ifmsg_iter_t iter;
|
2585
|
+
|
2586
|
+
if ((status = sigar_ifmsg_init(sigar)) != SIGAR_OK) {
|
2587
|
+
return status;
|
2588
|
+
}
|
2589
|
+
|
2590
|
+
iter.type = IFMSG_ITER_LIST;
|
2591
|
+
iter.data.iflist = iflist;
|
2592
|
+
|
2593
|
+
return sigar_ifmsg_iter(sigar, &iter);
|
2594
|
+
}
|
2595
|
+
|
2596
|
+
int sigar_net_interface_config_get(sigar_t *sigar, const char *name,
|
2597
|
+
sigar_net_interface_config_t *ifconfig)
|
2598
|
+
{
|
2599
|
+
int sock;
|
2600
|
+
int status;
|
2601
|
+
ifmsg_iter_t iter;
|
2602
|
+
struct if_msghdr *ifm;
|
2603
|
+
struct sockaddr_dl *sdl;
|
2604
|
+
struct ifreq ifr;
|
2605
|
+
|
2606
|
+
if (!name) {
|
2607
|
+
return sigar_net_interface_config_primary_get(sigar, ifconfig);
|
2608
|
+
}
|
2609
|
+
|
2610
|
+
if (sigar->ifconf_len == 0) {
|
2611
|
+
if ((status = sigar_ifmsg_init(sigar)) != SIGAR_OK) {
|
2612
|
+
return status;
|
2613
|
+
}
|
2614
|
+
}
|
2615
|
+
|
2616
|
+
SIGAR_ZERO(ifconfig);
|
2617
|
+
|
2618
|
+
iter.type = IFMSG_ITER_GET;
|
2619
|
+
iter.name = name;
|
2620
|
+
|
2621
|
+
if ((status = sigar_ifmsg_iter(sigar, &iter)) != SIGAR_OK) {
|
2622
|
+
return status;
|
2623
|
+
}
|
2624
|
+
|
2625
|
+
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
2626
|
+
return errno;
|
2627
|
+
}
|
2628
|
+
|
2629
|
+
ifm = iter.data.ifm;
|
2630
|
+
|
2631
|
+
SIGAR_SSTRCPY(ifconfig->name, name);
|
2632
|
+
|
2633
|
+
sdl = (struct sockaddr_dl *)(ifm + 1);
|
2634
|
+
|
2635
|
+
sigar_net_address_mac_set(ifconfig->hwaddr,
|
2636
|
+
LLADDR(sdl),
|
2637
|
+
sdl->sdl_alen);
|
2638
|
+
|
2639
|
+
ifconfig->flags = ifm->ifm_flags;
|
2640
|
+
ifconfig->mtu = ifm->ifm_data.ifi_mtu;
|
2641
|
+
ifconfig->metric = ifm->ifm_data.ifi_metric;
|
2642
|
+
|
2643
|
+
SIGAR_SSTRCPY(ifr.ifr_name, name);
|
2644
|
+
|
2645
|
+
#define ifr_s_addr(ifr) \
|
2646
|
+
((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr
|
2647
|
+
|
2648
|
+
if (!ioctl(sock, SIOCGIFADDR, &ifr)) {
|
2649
|
+
sigar_net_address_set(ifconfig->address,
|
2650
|
+
ifr_s_addr(ifr));
|
2651
|
+
}
|
2652
|
+
|
2653
|
+
if (!ioctl(sock, SIOCGIFNETMASK, &ifr)) {
|
2654
|
+
sigar_net_address_set(ifconfig->netmask,
|
2655
|
+
ifr_s_addr(ifr));
|
2656
|
+
}
|
2657
|
+
|
2658
|
+
if (ifconfig->flags & IFF_LOOPBACK) {
|
2659
|
+
sigar_net_address_set(ifconfig->destination,
|
2660
|
+
ifconfig->address.addr.in);
|
2661
|
+
sigar_net_address_set(ifconfig->broadcast, 0);
|
2662
|
+
SIGAR_SSTRCPY(ifconfig->type,
|
2663
|
+
SIGAR_NIC_LOOPBACK);
|
2664
|
+
}
|
2665
|
+
else {
|
2666
|
+
if (!ioctl(sock, SIOCGIFDSTADDR, &ifr)) {
|
2667
|
+
sigar_net_address_set(ifconfig->destination,
|
2668
|
+
ifr_s_addr(ifr));
|
2669
|
+
}
|
2670
|
+
|
2671
|
+
if (!ioctl(sock, SIOCGIFBRDADDR, &ifr)) {
|
2672
|
+
sigar_net_address_set(ifconfig->broadcast,
|
2673
|
+
ifr_s_addr(ifr));
|
2674
|
+
}
|
2675
|
+
SIGAR_SSTRCPY(ifconfig->type,
|
2676
|
+
SIGAR_NIC_ETHERNET);
|
2677
|
+
}
|
2678
|
+
|
2679
|
+
close(sock);
|
2680
|
+
|
2681
|
+
/* XXX can we get a better description like win32? */
|
2682
|
+
SIGAR_SSTRCPY(ifconfig->description,
|
2683
|
+
ifconfig->name);
|
2684
|
+
|
2685
|
+
return SIGAR_OK;
|
2686
|
+
}
|
2687
|
+
|
2688
|
+
int sigar_net_interface_stat_get(sigar_t *sigar, const char *name,
|
2689
|
+
sigar_net_interface_stat_t *ifstat)
|
2690
|
+
{
|
2691
|
+
int status;
|
2692
|
+
ifmsg_iter_t iter;
|
2693
|
+
struct if_msghdr *ifm;
|
2694
|
+
|
2695
|
+
if ((status = sigar_ifmsg_init(sigar)) != SIGAR_OK) {
|
2696
|
+
return status;
|
2697
|
+
}
|
2698
|
+
|
2699
|
+
iter.type = IFMSG_ITER_GET;
|
2700
|
+
iter.name = name;
|
2701
|
+
|
2702
|
+
if ((status = sigar_ifmsg_iter(sigar, &iter)) != SIGAR_OK) {
|
2703
|
+
return status;
|
2704
|
+
}
|
2705
|
+
|
2706
|
+
ifm = iter.data.ifm;
|
2707
|
+
|
2708
|
+
ifstat->rx_bytes = ifm->ifm_data.ifi_ibytes;
|
2709
|
+
ifstat->rx_packets = ifm->ifm_data.ifi_ipackets;
|
2710
|
+
ifstat->rx_errors = ifm->ifm_data.ifi_ierrors;
|
2711
|
+
ifstat->rx_dropped = ifm->ifm_data.ifi_iqdrops;
|
2712
|
+
ifstat->rx_overruns = SIGAR_FIELD_NOTIMPL;
|
2713
|
+
ifstat->rx_frame = SIGAR_FIELD_NOTIMPL;
|
2714
|
+
|
2715
|
+
ifstat->tx_bytes = ifm->ifm_data.ifi_obytes;
|
2716
|
+
ifstat->tx_packets = ifm->ifm_data.ifi_opackets;
|
2717
|
+
ifstat->tx_errors = ifm->ifm_data.ifi_oerrors;
|
2718
|
+
ifstat->tx_collisions = ifm->ifm_data.ifi_collisions;
|
2719
|
+
ifstat->tx_dropped = SIGAR_FIELD_NOTIMPL;
|
2720
|
+
ifstat->tx_overruns = SIGAR_FIELD_NOTIMPL;
|
2721
|
+
ifstat->tx_carrier = SIGAR_FIELD_NOTIMPL;
|
2722
|
+
|
2723
|
+
ifstat->speed = ifm->ifm_data.ifi_baudrate;
|
2724
|
+
|
2725
|
+
return SIGAR_OK;
|
2726
|
+
}
|
2727
|
+
|
2728
|
+
static int net_connection_state_get(int state)
|
2729
|
+
{
|
2730
|
+
switch (state) {
|
2731
|
+
case TCPS_CLOSED:
|
2732
|
+
return SIGAR_TCP_CLOSE;
|
2733
|
+
case TCPS_LISTEN:
|
2734
|
+
return SIGAR_TCP_LISTEN;
|
2735
|
+
case TCPS_SYN_SENT:
|
2736
|
+
return SIGAR_TCP_SYN_SENT;
|
2737
|
+
case TCPS_SYN_RECEIVED:
|
2738
|
+
return SIGAR_TCP_SYN_RECV;
|
2739
|
+
case TCPS_ESTABLISHED:
|
2740
|
+
return SIGAR_TCP_ESTABLISHED;
|
2741
|
+
case TCPS_CLOSE_WAIT:
|
2742
|
+
return SIGAR_TCP_CLOSE_WAIT;
|
2743
|
+
case TCPS_FIN_WAIT_1:
|
2744
|
+
return SIGAR_TCP_FIN_WAIT1;
|
2745
|
+
case TCPS_CLOSING:
|
2746
|
+
return SIGAR_TCP_CLOSING;
|
2747
|
+
case TCPS_LAST_ACK:
|
2748
|
+
return SIGAR_TCP_LAST_ACK;
|
2749
|
+
case TCPS_FIN_WAIT_2:
|
2750
|
+
return SIGAR_TCP_FIN_WAIT2;
|
2751
|
+
case TCPS_TIME_WAIT:
|
2752
|
+
return SIGAR_TCP_TIME_WAIT;
|
2753
|
+
default:
|
2754
|
+
return SIGAR_TCP_UNKNOWN;
|
2755
|
+
}
|
2756
|
+
}
|
2757
|
+
|
2758
|
+
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
2759
|
+
static int net_connection_get(sigar_net_connection_walker_t *walker, int proto)
|
2760
|
+
{
|
2761
|
+
int status;
|
2762
|
+
int istcp = 0, type;
|
2763
|
+
int flags = walker->flags;
|
2764
|
+
struct inpcbtable table;
|
2765
|
+
struct inpcb *head, *next, *prev;
|
2766
|
+
sigar_t *sigar = walker->sigar;
|
2767
|
+
u_long offset;
|
2768
|
+
|
2769
|
+
switch (proto) {
|
2770
|
+
case IPPROTO_TCP:
|
2771
|
+
offset = sigar->koffsets[KOFFSET_TCBTABLE];
|
2772
|
+
istcp = 1;
|
2773
|
+
type = SIGAR_NETCONN_TCP;
|
2774
|
+
break;
|
2775
|
+
case IPPROTO_UDP:
|
2776
|
+
default:
|
2777
|
+
return SIGAR_ENOTIMPL;
|
2778
|
+
}
|
2779
|
+
|
2780
|
+
|
2781
|
+
status = kread(sigar, &table, sizeof(table), offset);
|
2782
|
+
|
2783
|
+
if (status != SIGAR_OK) {
|
2784
|
+
return status;
|
2785
|
+
}
|
2786
|
+
|
2787
|
+
prev = head =
|
2788
|
+
(struct inpcb *)&CIRCLEQ_FIRST(&((struct inpcbtable *)offset)->inpt_queue);
|
2789
|
+
|
2790
|
+
next = (struct inpcb *)CIRCLEQ_FIRST(&table.inpt_queue);
|
2791
|
+
|
2792
|
+
while (next != head) {
|
2793
|
+
struct inpcb inpcb;
|
2794
|
+
struct tcpcb tcpcb;
|
2795
|
+
struct socket socket;
|
2796
|
+
|
2797
|
+
status = kread(sigar, &inpcb, sizeof(inpcb), (long)next);
|
2798
|
+
prev = next;
|
2799
|
+
next = (struct inpcb *)CIRCLEQ_NEXT(&inpcb, inp_queue);
|
2800
|
+
|
2801
|
+
kread(sigar, &socket, sizeof(socket), (u_long)inpcb.inp_socket);
|
2802
|
+
|
2803
|
+
if ((((flags & SIGAR_NETCONN_SERVER) && socket.so_qlimit) ||
|
2804
|
+
((flags & SIGAR_NETCONN_CLIENT) && !socket.so_qlimit)))
|
2805
|
+
{
|
2806
|
+
sigar_net_connection_t conn;
|
2807
|
+
|
2808
|
+
SIGAR_ZERO(&conn);
|
2809
|
+
|
2810
|
+
if (istcp) {
|
2811
|
+
kread(sigar, &tcpcb, sizeof(tcpcb), (u_long)inpcb.inp_ppcb);
|
2812
|
+
}
|
2813
|
+
|
2814
|
+
#ifdef __NetBSD__
|
2815
|
+
if (inpcb.inp_af == AF_INET6) {
|
2816
|
+
/*XXX*/
|
2817
|
+
continue;
|
2818
|
+
}
|
2819
|
+
#else
|
2820
|
+
if (inpcb.inp_flags & INP_IPV6) {
|
2821
|
+
sigar_net_address6_set(conn.local_address,
|
2822
|
+
&inpcb.inp_laddr6.s6_addr);
|
2823
|
+
|
2824
|
+
sigar_net_address6_set(conn.remote_address,
|
2825
|
+
&inpcb.inp_faddr6.s6_addr);
|
2826
|
+
}
|
2827
|
+
#endif
|
2828
|
+
else {
|
2829
|
+
sigar_net_address_set(conn.local_address,
|
2830
|
+
inpcb.inp_laddr.s_addr);
|
2831
|
+
|
2832
|
+
sigar_net_address_set(conn.remote_address,
|
2833
|
+
inpcb.inp_faddr.s_addr);
|
2834
|
+
}
|
2835
|
+
|
2836
|
+
conn.local_port = ntohs(inpcb.inp_lport);
|
2837
|
+
conn.remote_port = ntohs(inpcb.inp_fport);
|
2838
|
+
conn.receive_queue = socket.so_rcv.sb_cc;
|
2839
|
+
conn.send_queue = socket.so_snd.sb_cc;
|
2840
|
+
conn.uid = socket.so_pgid;
|
2841
|
+
conn.type = type;
|
2842
|
+
|
2843
|
+
if (!istcp) {
|
2844
|
+
conn.state = SIGAR_TCP_UNKNOWN;
|
2845
|
+
if (walker->add_connection(walker, &conn) != SIGAR_OK) {
|
2846
|
+
break;
|
2847
|
+
}
|
2848
|
+
continue;
|
2849
|
+
}
|
2850
|
+
|
2851
|
+
conn.state = net_connection_state_get(tcpcb.t_state);
|
2852
|
+
|
2853
|
+
if (walker->add_connection(walker, &conn) != SIGAR_OK) {
|
2854
|
+
break;
|
2855
|
+
}
|
2856
|
+
}
|
2857
|
+
}
|
2858
|
+
|
2859
|
+
return SIGAR_OK;
|
2860
|
+
}
|
2861
|
+
#else
|
2862
|
+
static int net_connection_get(sigar_net_connection_walker_t *walker, int proto)
|
2863
|
+
{
|
2864
|
+
int flags = walker->flags;
|
2865
|
+
int type, istcp = 0;
|
2866
|
+
char *buf;
|
2867
|
+
const char *mibvar;
|
2868
|
+
struct tcpcb *tp = NULL;
|
2869
|
+
struct inpcb *inp;
|
2870
|
+
struct xinpgen *xig, *oxig;
|
2871
|
+
struct xsocket *so;
|
2872
|
+
size_t len;
|
2873
|
+
|
2874
|
+
switch (proto) {
|
2875
|
+
case IPPROTO_TCP:
|
2876
|
+
mibvar = "net.inet.tcp.pcblist";
|
2877
|
+
istcp = 1;
|
2878
|
+
type = SIGAR_NETCONN_TCP;
|
2879
|
+
break;
|
2880
|
+
case IPPROTO_UDP:
|
2881
|
+
mibvar = "net.inet.udp.pcblist";
|
2882
|
+
type = SIGAR_NETCONN_UDP;
|
2883
|
+
break;
|
2884
|
+
default:
|
2885
|
+
mibvar = "net.inet.raw.pcblist";
|
2886
|
+
type = SIGAR_NETCONN_RAW;
|
2887
|
+
break;
|
2888
|
+
}
|
2889
|
+
|
2890
|
+
len = 0;
|
2891
|
+
if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
|
2892
|
+
return errno;
|
2893
|
+
}
|
2894
|
+
if ((buf = malloc(len)) == 0) {
|
2895
|
+
return errno;
|
2896
|
+
}
|
2897
|
+
if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
|
2898
|
+
free(buf);
|
2899
|
+
return errno;
|
2900
|
+
}
|
2901
|
+
|
2902
|
+
oxig = xig = (struct xinpgen *)buf;
|
2903
|
+
for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
|
2904
|
+
xig->xig_len > sizeof(struct xinpgen);
|
2905
|
+
xig = (struct xinpgen *)((char *)xig + xig->xig_len))
|
2906
|
+
{
|
2907
|
+
if (istcp) {
|
2908
|
+
struct xtcpcb *cb = (struct xtcpcb *)xig;
|
2909
|
+
tp = &cb->xt_tp;
|
2910
|
+
inp = &cb->xt_inp;
|
2911
|
+
so = &cb->xt_socket;
|
2912
|
+
}
|
2913
|
+
else {
|
2914
|
+
struct xinpcb *cb = (struct xinpcb *)xig;
|
2915
|
+
inp = &cb->xi_inp;
|
2916
|
+
so = &cb->xi_socket;
|
2917
|
+
}
|
2918
|
+
|
2919
|
+
if (so->xso_protocol != proto) {
|
2920
|
+
continue;
|
2921
|
+
}
|
2922
|
+
|
2923
|
+
if (inp->inp_gencnt > oxig->xig_gen) {
|
2924
|
+
continue;
|
2925
|
+
}
|
2926
|
+
|
2927
|
+
if ((((flags & SIGAR_NETCONN_SERVER) && so->so_qlimit) ||
|
2928
|
+
((flags & SIGAR_NETCONN_CLIENT) && !so->so_qlimit)))
|
2929
|
+
{
|
2930
|
+
sigar_net_connection_t conn;
|
2931
|
+
|
2932
|
+
SIGAR_ZERO(&conn);
|
2933
|
+
|
2934
|
+
if (inp->inp_vflag & INP_IPV6) {
|
2935
|
+
sigar_net_address6_set(conn.local_address,
|
2936
|
+
&inp->in6p_laddr.s6_addr);
|
2937
|
+
|
2938
|
+
sigar_net_address6_set(conn.remote_address,
|
2939
|
+
&inp->in6p_faddr.s6_addr);
|
2940
|
+
}
|
2941
|
+
else {
|
2942
|
+
sigar_net_address_set(conn.local_address,
|
2943
|
+
inp->inp_laddr.s_addr);
|
2944
|
+
|
2945
|
+
sigar_net_address_set(conn.remote_address,
|
2946
|
+
inp->inp_faddr.s_addr);
|
2947
|
+
}
|
2948
|
+
|
2949
|
+
conn.local_port = ntohs(inp->inp_lport);
|
2950
|
+
conn.remote_port = ntohs(inp->inp_fport);
|
2951
|
+
conn.receive_queue = so->so_rcv.sb_cc;
|
2952
|
+
conn.send_queue = so->so_snd.sb_cc;
|
2953
|
+
conn.uid = so->so_pgid;
|
2954
|
+
conn.type = type;
|
2955
|
+
|
2956
|
+
if (!istcp) {
|
2957
|
+
conn.state = SIGAR_TCP_UNKNOWN;
|
2958
|
+
if (walker->add_connection(walker, &conn) != SIGAR_OK) {
|
2959
|
+
break;
|
2960
|
+
}
|
2961
|
+
continue;
|
2962
|
+
}
|
2963
|
+
|
2964
|
+
conn.state = net_connection_state_get(tp->t_state);
|
2965
|
+
|
2966
|
+
if (walker->add_connection(walker, &conn) != SIGAR_OK) {
|
2967
|
+
break;
|
2968
|
+
}
|
2969
|
+
}
|
2970
|
+
}
|
2971
|
+
|
2972
|
+
free(buf);
|
2973
|
+
|
2974
|
+
return SIGAR_OK;
|
2975
|
+
}
|
2976
|
+
#endif
|
2977
|
+
|
2978
|
+
int sigar_net_connection_walk(sigar_net_connection_walker_t *walker)
|
2979
|
+
{
|
2980
|
+
int flags = walker->flags;
|
2981
|
+
int status;
|
2982
|
+
|
2983
|
+
if (flags & SIGAR_NETCONN_TCP) {
|
2984
|
+
status = net_connection_get(walker, IPPROTO_TCP);
|
2985
|
+
if (status != SIGAR_OK) {
|
2986
|
+
return status;
|
2987
|
+
}
|
2988
|
+
}
|
2989
|
+
if (flags & SIGAR_NETCONN_UDP) {
|
2990
|
+
status = net_connection_get(walker, IPPROTO_UDP);
|
2991
|
+
if (status != SIGAR_OK) {
|
2992
|
+
return status;
|
2993
|
+
}
|
2994
|
+
}
|
2995
|
+
|
2996
|
+
return SIGAR_OK;
|
2997
|
+
}
|
2998
|
+
|
2999
|
+
SIGAR_DECLARE(int)
|
3000
|
+
sigar_tcp_get(sigar_t *sigar,
|
3001
|
+
sigar_tcp_t *tcp)
|
3002
|
+
{
|
3003
|
+
struct tcpstat mib;
|
3004
|
+
#if !defined(TCPCTL_STATS) && (defined(__OpenBSD__) || defined(__NetBSD__))
|
3005
|
+
int status =
|
3006
|
+
kread(sigar, &mib, sizeof(mib),
|
3007
|
+
sigar->koffsets[KOFFSET_TCPSTAT]);
|
3008
|
+
if (status != SIGAR_OK) {
|
3009
|
+
return status;
|
3010
|
+
}
|
3011
|
+
#else
|
3012
|
+
int var[4] = { CTL_NET, PF_INET, IPPROTO_TCP, TCPCTL_STATS };
|
3013
|
+
size_t len = sizeof(mib);
|
3014
|
+
|
3015
|
+
if (sysctl(var, NMIB(var), &mib, &len, NULL, 0) < 0) {
|
3016
|
+
return errno;
|
3017
|
+
}
|
3018
|
+
#endif
|
3019
|
+
|
3020
|
+
tcp->active_opens = mib.tcps_connattempt;
|
3021
|
+
tcp->passive_opens = mib.tcps_accepts;
|
3022
|
+
tcp->attempt_fails = mib.tcps_conndrops;
|
3023
|
+
tcp->estab_resets = mib.tcps_drops;
|
3024
|
+
if (sigar_tcp_curr_estab(sigar, tcp) != SIGAR_OK) {
|
3025
|
+
tcp->curr_estab = -1;
|
3026
|
+
}
|
3027
|
+
tcp->in_segs = mib.tcps_rcvtotal;
|
3028
|
+
tcp->out_segs = mib.tcps_sndtotal - mib.tcps_sndrexmitpack;
|
3029
|
+
tcp->retrans_segs = mib.tcps_sndrexmitpack;
|
3030
|
+
tcp->in_errs =
|
3031
|
+
mib.tcps_rcvbadsum +
|
3032
|
+
mib.tcps_rcvbadoff +
|
3033
|
+
mib.tcps_rcvmemdrop +
|
3034
|
+
mib.tcps_rcvshort;
|
3035
|
+
tcp->out_rsts = -1; /* XXX mib.tcps_sndctrl - mib.tcps_closed; ? */
|
3036
|
+
|
3037
|
+
return SIGAR_OK;
|
3038
|
+
}
|
3039
|
+
|
3040
|
+
#ifndef SIGAR_FREEBSD5_NFSSTAT
|
3041
|
+
static int get_nfsstats(struct nfsstats *stats)
|
3042
|
+
{
|
3043
|
+
size_t len = sizeof(*stats);
|
3044
|
+
int mib[] = { CTL_VFS, 2, NFS_NFSSTATS };
|
3045
|
+
|
3046
|
+
if (sysctl(mib, NMIB(mib), stats, &len, NULL, 0) < 0) {
|
3047
|
+
return errno;
|
3048
|
+
}
|
3049
|
+
else {
|
3050
|
+
return SIGAR_OK;
|
3051
|
+
}
|
3052
|
+
}
|
3053
|
+
#endif
|
3054
|
+
|
3055
|
+
#if defined(__OpenBSD__)
|
3056
|
+
typedef uint64_t rpc_cnt_t;
|
3057
|
+
#else
|
3058
|
+
typedef int rpc_cnt_t;
|
3059
|
+
#endif
|
3060
|
+
|
3061
|
+
static void map_nfs_stats(sigar_nfs_v3_t *nfs, rpc_cnt_t *rpc)
|
3062
|
+
{
|
3063
|
+
nfs->null = rpc[NFSPROC_NULL];
|
3064
|
+
nfs->getattr = rpc[NFSPROC_GETATTR];
|
3065
|
+
nfs->setattr = rpc[NFSPROC_SETATTR];
|
3066
|
+
nfs->lookup = rpc[NFSPROC_LOOKUP];
|
3067
|
+
nfs->access = rpc[NFSPROC_ACCESS];
|
3068
|
+
nfs->readlink = rpc[NFSPROC_READLINK];
|
3069
|
+
nfs->read = rpc[NFSPROC_READ];
|
3070
|
+
nfs->write = rpc[NFSPROC_WRITE];
|
3071
|
+
nfs->create = rpc[NFSPROC_CREATE];
|
3072
|
+
nfs->mkdir = rpc[NFSPROC_MKDIR];
|
3073
|
+
nfs->symlink = rpc[NFSPROC_SYMLINK];
|
3074
|
+
nfs->mknod = rpc[NFSPROC_MKNOD];
|
3075
|
+
nfs->remove = rpc[NFSPROC_REMOVE];
|
3076
|
+
nfs->rmdir = rpc[NFSPROC_RMDIR];
|
3077
|
+
nfs->rename = rpc[NFSPROC_RENAME];
|
3078
|
+
nfs->link = rpc[NFSPROC_LINK];
|
3079
|
+
nfs->readdir = rpc[NFSPROC_READDIR];
|
3080
|
+
nfs->readdirplus = rpc[NFSPROC_READDIRPLUS];
|
3081
|
+
nfs->fsstat = rpc[NFSPROC_FSSTAT];
|
3082
|
+
nfs->fsinfo = rpc[NFSPROC_FSINFO];
|
3083
|
+
nfs->pathconf = rpc[NFSPROC_PATHCONF];
|
3084
|
+
nfs->commit = rpc[NFSPROC_COMMIT];
|
3085
|
+
}
|
3086
|
+
|
3087
|
+
int sigar_nfs_client_v2_get(sigar_t *sigar,
|
3088
|
+
sigar_nfs_client_v2_t *nfs)
|
3089
|
+
{
|
3090
|
+
return SIGAR_ENOTIMPL;
|
3091
|
+
}
|
3092
|
+
|
3093
|
+
int sigar_nfs_server_v2_get(sigar_t *sigar,
|
3094
|
+
sigar_nfs_server_v2_t *nfs)
|
3095
|
+
{
|
3096
|
+
return SIGAR_ENOTIMPL;
|
3097
|
+
}
|
3098
|
+
|
3099
|
+
int sigar_nfs_client_v3_get(sigar_t *sigar,
|
3100
|
+
sigar_nfs_client_v3_t *nfs)
|
3101
|
+
{
|
3102
|
+
#ifdef SIGAR_FREEBSD5_NFSSTAT
|
3103
|
+
struct nfsstats stats;
|
3104
|
+
size_t size = sizeof(stats);
|
3105
|
+
|
3106
|
+
if (sysctlbyname("vfs.nfs.nfsstats", &stats, &size, NULL, 0) == -1) {
|
3107
|
+
return errno;
|
3108
|
+
}
|
3109
|
+
|
3110
|
+
map_nfs_stats((sigar_nfs_v3_t *)nfs, &stats.rpccnt[0]);
|
3111
|
+
#else
|
3112
|
+
int status;
|
3113
|
+
struct nfsstats stats;
|
3114
|
+
|
3115
|
+
if ((status = get_nfsstats(&stats)) != SIGAR_OK) {
|
3116
|
+
return status;
|
3117
|
+
}
|
3118
|
+
|
3119
|
+
map_nfs_stats((sigar_nfs_v3_t *)nfs, &stats.rpccnt[0]);
|
3120
|
+
#endif
|
3121
|
+
|
3122
|
+
return SIGAR_OK;
|
3123
|
+
}
|
3124
|
+
|
3125
|
+
int sigar_nfs_server_v3_get(sigar_t *sigar,
|
3126
|
+
sigar_nfs_server_v3_t *nfs)
|
3127
|
+
{
|
3128
|
+
#ifdef SIGAR_FREEBSD5_NFSSTAT
|
3129
|
+
struct nfsrvstats stats;
|
3130
|
+
size_t size = sizeof(stats);
|
3131
|
+
|
3132
|
+
if (sysctlbyname("vfs.nfsrv.nfsrvstats", &stats, &size, NULL, 0) == -1) {
|
3133
|
+
return errno;
|
3134
|
+
}
|
3135
|
+
|
3136
|
+
map_nfs_stats((sigar_nfs_v3_t *)nfs, &stats.srvrpccnt[0]);
|
3137
|
+
#else
|
3138
|
+
int status;
|
3139
|
+
struct nfsstats stats;
|
3140
|
+
|
3141
|
+
if ((status = get_nfsstats(&stats)) != SIGAR_OK) {
|
3142
|
+
return status;
|
3143
|
+
}
|
3144
|
+
|
3145
|
+
map_nfs_stats((sigar_nfs_v3_t *)nfs, &stats.srvrpccnt[0]);
|
3146
|
+
#endif
|
3147
|
+
|
3148
|
+
return SIGAR_OK;
|
3149
|
+
}
|
3150
|
+
|
3151
|
+
#if defined(__FreeBSD__)
|
3152
|
+
|
3153
|
+
#define _KERNEL
|
3154
|
+
#include <sys/file.h>
|
3155
|
+
#undef _KERNEL
|
3156
|
+
|
3157
|
+
/* derived from
|
3158
|
+
* /usr/ports/security/pidentd/work/pidentd-3.0.16/src/k_freebsd2.c
|
3159
|
+
*/
|
3160
|
+
int sigar_proc_port_get(sigar_t *sigar, int protocol,
|
3161
|
+
unsigned long port, sigar_pid_t *pid)
|
3162
|
+
{
|
3163
|
+
struct nlist nl[2];
|
3164
|
+
struct inpcbhead tcb;
|
3165
|
+
struct socket *sockp = NULL;
|
3166
|
+
struct kinfo_proc *pinfo;
|
3167
|
+
struct inpcb *head, pcbp;
|
3168
|
+
int i, nentries, status;
|
3169
|
+
|
3170
|
+
if (protocol != SIGAR_NETCONN_TCP) {
|
3171
|
+
return SIGAR_ENOTIMPL;
|
3172
|
+
}
|
3173
|
+
|
3174
|
+
if (!sigar->kmem) {
|
3175
|
+
return SIGAR_EPERM_KMEM;
|
3176
|
+
}
|
3177
|
+
|
3178
|
+
nl[0].n_name = "_tcb"; /* XXX cache */
|
3179
|
+
nl[1].n_name = "";
|
3180
|
+
if (kvm_nlist(sigar->kmem, nl) < 0) {
|
3181
|
+
return errno;
|
3182
|
+
}
|
3183
|
+
|
3184
|
+
status = kread(sigar, &tcb, sizeof(tcb), nl[0].n_value);
|
3185
|
+
if (status != SIGAR_OK) {
|
3186
|
+
return status;
|
3187
|
+
}
|
3188
|
+
|
3189
|
+
for (head = tcb.lh_first; head != NULL;
|
3190
|
+
head = pcbp.inp_list.le_next)
|
3191
|
+
{
|
3192
|
+
status = kread(sigar, &pcbp, sizeof(pcbp), (long)head);
|
3193
|
+
if (status != SIGAR_OK) {
|
3194
|
+
return status;
|
3195
|
+
}
|
3196
|
+
if (!(pcbp.inp_vflag & INP_IPV4)) {
|
3197
|
+
continue;
|
3198
|
+
}
|
3199
|
+
if (pcbp.inp_fport != 0) {
|
3200
|
+
continue;
|
3201
|
+
}
|
3202
|
+
if (ntohs(pcbp.inp_lport) == port) {
|
3203
|
+
sockp = pcbp.inp_socket;
|
3204
|
+
break;
|
3205
|
+
}
|
3206
|
+
}
|
3207
|
+
|
3208
|
+
if (!sockp) {
|
3209
|
+
return ENOENT;
|
3210
|
+
}
|
3211
|
+
|
3212
|
+
pinfo = kvm_getprocs(sigar->kmem, KERN_PROC_PROC, 0, &nentries);
|
3213
|
+
if (!pinfo) {
|
3214
|
+
return errno;
|
3215
|
+
}
|
3216
|
+
|
3217
|
+
for (i=0; i<nentries; i++) {
|
3218
|
+
if (pinfo[i].KI_FLAG & P_SYSTEM) {
|
3219
|
+
continue;
|
3220
|
+
}
|
3221
|
+
if (pinfo[i].KI_FD) {
|
3222
|
+
struct filedesc pfd;
|
3223
|
+
struct file **ofiles, ofile;
|
3224
|
+
int j, osize;
|
3225
|
+
|
3226
|
+
status = kread(sigar, &pfd, sizeof(pfd), (long)pinfo[i].KI_FD);
|
3227
|
+
if (status != SIGAR_OK) {
|
3228
|
+
return status;
|
3229
|
+
}
|
3230
|
+
|
3231
|
+
osize = pfd.fd_nfiles * sizeof(struct file *);
|
3232
|
+
ofiles = malloc(osize); /* XXX reuse */
|
3233
|
+
if (!ofiles) {
|
3234
|
+
return errno;
|
3235
|
+
}
|
3236
|
+
|
3237
|
+
status = kread(sigar, ofiles, osize, (long)pfd.fd_ofiles);
|
3238
|
+
if (status != SIGAR_OK) {
|
3239
|
+
free(ofiles);
|
3240
|
+
return status;
|
3241
|
+
}
|
3242
|
+
|
3243
|
+
for (j=0; j<pfd.fd_nfiles; j++) {
|
3244
|
+
if (!ofiles[j]) {
|
3245
|
+
continue;
|
3246
|
+
}
|
3247
|
+
|
3248
|
+
status = kread(sigar, &ofile, sizeof(ofile), (long)ofiles[j]);
|
3249
|
+
if (status != SIGAR_OK) {
|
3250
|
+
free(ofiles);
|
3251
|
+
return status;
|
3252
|
+
}
|
3253
|
+
|
3254
|
+
if (ofile.f_count == 0) {
|
3255
|
+
continue;
|
3256
|
+
}
|
3257
|
+
|
3258
|
+
if (ofile.f_type == DTYPE_SOCKET &&
|
3259
|
+
(struct socket *)ofile.f_data == sockp)
|
3260
|
+
{
|
3261
|
+
*pid = pinfo[i].KI_PID;
|
3262
|
+
free(ofiles);
|
3263
|
+
return SIGAR_OK;
|
3264
|
+
}
|
3265
|
+
}
|
3266
|
+
|
3267
|
+
free(ofiles);
|
3268
|
+
}
|
3269
|
+
}
|
3270
|
+
|
3271
|
+
return ENOENT;
|
3272
|
+
}
|
3273
|
+
|
3274
|
+
#elif defined(DARWIN) && defined(DARWIN_HAS_LIBPROC_H)
|
3275
|
+
|
3276
|
+
int sigar_proc_port_get(sigar_t *sigar, int protocol,
|
3277
|
+
unsigned long port, sigar_pid_t *pid)
|
3278
|
+
{
|
3279
|
+
sigar_proc_list_t pids;
|
3280
|
+
int i, status, found=0;
|
3281
|
+
|
3282
|
+
if (!sigar->libproc) {
|
3283
|
+
return SIGAR_ENOTIMPL;
|
3284
|
+
}
|
3285
|
+
|
3286
|
+
status = sigar_proc_list_get(sigar, &pids);
|
3287
|
+
if (status != SIGAR_OK) {
|
3288
|
+
return status;
|
3289
|
+
}
|
3290
|
+
|
3291
|
+
for (i=0; i<pids.number; i++) {
|
3292
|
+
int n, num=0;
|
3293
|
+
struct proc_fdinfo *fdinfo;
|
3294
|
+
|
3295
|
+
status = proc_fdinfo_get(sigar, pids.data[i], &num);
|
3296
|
+
if (status != SIGAR_OK) {
|
3297
|
+
continue;
|
3298
|
+
}
|
3299
|
+
fdinfo = (struct proc_fdinfo *)sigar->ifconf_buf;
|
3300
|
+
|
3301
|
+
for (n=0; n<num; n++) {
|
3302
|
+
struct proc_fdinfo *fdp = &fdinfo[n];
|
3303
|
+
struct socket_fdinfo si;
|
3304
|
+
int rsize, family;
|
3305
|
+
unsigned long lport;
|
3306
|
+
|
3307
|
+
if (fdp->proc_fdtype != PROX_FDTYPE_SOCKET) {
|
3308
|
+
continue;
|
3309
|
+
}
|
3310
|
+
rsize = sigar->proc_pidfdinfo(pids.data[i], fdp->proc_fd,
|
3311
|
+
PROC_PIDFDSOCKETINFO, &si, sizeof(si));
|
3312
|
+
if (rsize != sizeof(si)) {
|
3313
|
+
continue;
|
3314
|
+
}
|
3315
|
+
if (si.psi.soi_kind != SOCKINFO_TCP) {
|
3316
|
+
continue;
|
3317
|
+
}
|
3318
|
+
if (si.psi.soi_proto.pri_tcp.tcpsi_state != TSI_S_LISTEN) {
|
3319
|
+
continue;
|
3320
|
+
}
|
3321
|
+
family = si.psi.soi_family;
|
3322
|
+
if (!((family == AF_INET) || (family == AF_INET6))) {
|
3323
|
+
continue;
|
3324
|
+
}
|
3325
|
+
lport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport);
|
3326
|
+
if (lport == port) {
|
3327
|
+
*pid = pids.data[i];
|
3328
|
+
found = 1;
|
3329
|
+
break;
|
3330
|
+
}
|
3331
|
+
}
|
3332
|
+
}
|
3333
|
+
|
3334
|
+
sigar_proc_list_destroy(sigar, &pids);
|
3335
|
+
|
3336
|
+
return found ? SIGAR_OK : ENOENT;
|
3337
|
+
}
|
3338
|
+
|
3339
|
+
#else
|
3340
|
+
|
3341
|
+
int sigar_proc_port_get(sigar_t *sigar, int protocol,
|
3342
|
+
unsigned long port, sigar_pid_t *pid)
|
3343
|
+
{
|
3344
|
+
return SIGAR_ENOTIMPL;
|
3345
|
+
}
|
3346
|
+
|
3347
|
+
#endif
|
3348
|
+
|
3349
|
+
int sigar_os_sys_info_get(sigar_t *sigar,
|
3350
|
+
sigar_sys_info_t *sysinfo)
|
3351
|
+
{
|
3352
|
+
#ifdef DARWIN
|
3353
|
+
char *codename = NULL;
|
3354
|
+
SInt32 version, version_major, version_minor, version_fix;
|
3355
|
+
|
3356
|
+
SIGAR_SSTRCPY(sysinfo->name, "MacOSX");
|
3357
|
+
SIGAR_SSTRCPY(sysinfo->vendor_name, "Mac OS X");
|
3358
|
+
SIGAR_SSTRCPY(sysinfo->vendor, "Apple");
|
3359
|
+
|
3360
|
+
if (Gestalt(gestaltSystemVersion, &version) == noErr) {
|
3361
|
+
if (version >= 0x00001040) {
|
3362
|
+
Gestalt('sys1' /*gestaltSystemVersionMajor*/, &version_major);
|
3363
|
+
Gestalt('sys2' /*gestaltSystemVersionMinor*/, &version_minor);
|
3364
|
+
Gestalt('sys3' /*gestaltSystemVersionBugFix*/, &version_fix);
|
3365
|
+
}
|
3366
|
+
else {
|
3367
|
+
version_fix = version & 0xf;
|
3368
|
+
version >>= 4;
|
3369
|
+
version_minor = version & 0xf;
|
3370
|
+
version >>= 4;
|
3371
|
+
version_major = version - (version >> 4) * 6;
|
3372
|
+
}
|
3373
|
+
}
|
3374
|
+
else {
|
3375
|
+
return SIGAR_ENOTIMPL;
|
3376
|
+
}
|
3377
|
+
|
3378
|
+
snprintf(sysinfo->vendor_version,
|
3379
|
+
sizeof(sysinfo->vendor_version),
|
3380
|
+
"%d.%d",
|
3381
|
+
(int)version_major, (int)version_minor);
|
3382
|
+
|
3383
|
+
snprintf(sysinfo->version,
|
3384
|
+
sizeof(sysinfo->version),
|
3385
|
+
"%s.%d",
|
3386
|
+
sysinfo->vendor_version, (int)version_fix);
|
3387
|
+
|
3388
|
+
if (version_major == 10) {
|
3389
|
+
switch (version_minor) {
|
3390
|
+
case 2:
|
3391
|
+
codename = "Jaguar";
|
3392
|
+
break;
|
3393
|
+
case 3:
|
3394
|
+
codename = "Panther";
|
3395
|
+
break;
|
3396
|
+
case 4:
|
3397
|
+
codename = "Tiger";
|
3398
|
+
break;
|
3399
|
+
case 5:
|
3400
|
+
codename = "Leopard";
|
3401
|
+
break;
|
3402
|
+
case 6:
|
3403
|
+
codename = "Snow Leopard";
|
3404
|
+
break;
|
3405
|
+
default:
|
3406
|
+
codename = "Unknown";
|
3407
|
+
break;
|
3408
|
+
}
|
3409
|
+
}
|
3410
|
+
else {
|
3411
|
+
return SIGAR_ENOTIMPL;
|
3412
|
+
}
|
3413
|
+
|
3414
|
+
SIGAR_SSTRCPY(sysinfo->vendor_code_name, codename);
|
3415
|
+
|
3416
|
+
snprintf(sysinfo->description,
|
3417
|
+
sizeof(sysinfo->description),
|
3418
|
+
"%s %s",
|
3419
|
+
sysinfo->vendor_name, sysinfo->vendor_code_name);
|
3420
|
+
#else
|
3421
|
+
char *ptr;
|
3422
|
+
|
3423
|
+
#if defined(__FreeBSD__)
|
3424
|
+
SIGAR_SSTRCPY(sysinfo->name, "FreeBSD");
|
3425
|
+
#elif defined(__OpenBSD__)
|
3426
|
+
SIGAR_SSTRCPY(sysinfo->name, "OpenBSD");
|
3427
|
+
#elif defined(__NetBSD__)
|
3428
|
+
SIGAR_SSTRCPY(sysinfo->name, "NetBSD");
|
3429
|
+
#else
|
3430
|
+
SIGAR_SSTRCPY(sysinfo->name, "Unknown");
|
3431
|
+
#endif
|
3432
|
+
SIGAR_SSTRCPY(sysinfo->vendor_name, sysinfo->name);
|
3433
|
+
SIGAR_SSTRCPY(sysinfo->vendor, sysinfo->name);
|
3434
|
+
SIGAR_SSTRCPY(sysinfo->vendor_version,
|
3435
|
+
sysinfo->version);
|
3436
|
+
|
3437
|
+
if ((ptr = strstr(sysinfo->vendor_version, "-"))) {
|
3438
|
+
/* STABLE, RELEASE, CURRENT */
|
3439
|
+
*ptr++ = '\0';
|
3440
|
+
SIGAR_SSTRCPY(sysinfo->vendor_code_name, ptr);
|
3441
|
+
}
|
3442
|
+
|
3443
|
+
snprintf(sysinfo->description,
|
3444
|
+
sizeof(sysinfo->description),
|
3445
|
+
"%s %s",
|
3446
|
+
sysinfo->name, sysinfo->version);
|
3447
|
+
#endif
|
3448
|
+
|
3449
|
+
return SIGAR_OK;
|
3450
|
+
}
|