sigar-test 0.7.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }