sigar 0.7.0

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