sigar-test 0.7.3.1

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