sigar-test 0.7.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/NOTICE +117 -0
  4. data/README +2 -0
  5. data/Rakefile +105 -0
  6. data/bindings/SigarBuild.pm +301 -0
  7. data/bindings/SigarWrapper.pm +3025 -0
  8. data/bindings/ruby/extconf.rb +131 -0
  9. data/bindings/ruby/rbsigar.c +888 -0
  10. data/include/sigar.h +984 -0
  11. data/include/sigar_fileinfo.h +157 -0
  12. data/include/sigar_format.h +65 -0
  13. data/include/sigar_getline.h +18 -0
  14. data/include/sigar_log.h +80 -0
  15. data/include/sigar_private.h +429 -0
  16. data/include/sigar_ptql.h +53 -0
  17. data/include/sigar_util.h +197 -0
  18. data/src/os/aix/aix_sigar.c +2168 -0
  19. data/src/os/aix/sigar_os.h +73 -0
  20. data/src/os/darwin/Info.plist.in +27 -0
  21. data/src/os/darwin/darwin_sigar.c +3718 -0
  22. data/src/os/darwin/sigar_os.h +80 -0
  23. data/src/os/hpux/hpux_sigar.c +1361 -0
  24. data/src/os/hpux/sigar_os.h +49 -0
  25. data/src/os/linux/linux_sigar.c +2810 -0
  26. data/src/os/linux/sigar_os.h +82 -0
  27. data/src/os/solaris/get_mib2.c +321 -0
  28. data/src/os/solaris/get_mib2.h +127 -0
  29. data/src/os/solaris/kstats.c +181 -0
  30. data/src/os/solaris/procfs.c +97 -0
  31. data/src/os/solaris/sigar_os.h +224 -0
  32. data/src/os/solaris/solaris_sigar.c +2732 -0
  33. data/src/os/win32/peb.c +212 -0
  34. data/src/os/win32/sigar.rc.in +40 -0
  35. data/src/os/win32/sigar_os.h +685 -0
  36. data/src/os/win32/sigar_pdh.h +47 -0
  37. data/src/os/win32/win32_sigar.c +4109 -0
  38. data/src/sigar.c +2444 -0
  39. data/src/sigar_cache.c +253 -0
  40. data/src/sigar_fileinfo.c +815 -0
  41. data/src/sigar_format.c +696 -0
  42. data/src/sigar_getline.c +1849 -0
  43. data/src/sigar_ptql.c +1976 -0
  44. data/src/sigar_signal.c +216 -0
  45. data/src/sigar_util.c +1060 -0
  46. data/src/sigar_version.c.in +22 -0
  47. data/src/sigar_version_autoconf.c.in +22 -0
  48. data/version.properties +11 -0
  49. metadata +91 -0
@@ -0,0 +1,2732 @@
1
+ /*
2
+ * Copyright (c) 2004-2008 Hyperic, Inc.
3
+ * Copyright (c) 2009 SpringSource, Inc.
4
+ * Copyright (c) 2009-2010 VMware, Inc.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ #include "sigar.h"
20
+ #include "sigar_private.h"
21
+ #include "sigar_util.h"
22
+ #include "sigar_os.h"
23
+
24
+ #include <inet/ip.h>
25
+ #include <inet/tcp.h>
26
+ #include <net/if.h>
27
+ #include <net/route.h>
28
+ #include <sys/lwp.h>
29
+ #include <sys/proc.h>
30
+ #include <sys/sockio.h>
31
+ #include <sys/swap.h>
32
+ #include <sys/stat.h>
33
+ #include <sys/systeminfo.h>
34
+ #include <sys/utsname.h>
35
+ #include <dlfcn.h>
36
+ #include <dirent.h>
37
+
38
+ #define PROC_ERRNO ((errno == ENOENT) ? ESRCH : errno)
39
+ #define SIGAR_USR_UCB_PS "/usr/ucb/ps"
40
+
41
+
42
+ /* like kstat_lookup but start w/ ksp->ks_next instead of kc->kc_chain */
43
+ static kstat_t *
44
+ kstat_next(kstat_t *ksp, char *ks_module, int ks_instance, char *ks_name)
45
+ {
46
+ if (ksp) {
47
+ ksp = ksp->ks_next;
48
+ }
49
+ for (; ksp; ksp = ksp->ks_next) {
50
+ if ((ks_module == NULL ||
51
+ strcmp(ksp->ks_module, ks_module) == 0) &&
52
+ (ks_instance == -1 || ksp->ks_instance == ks_instance) &&
53
+ (ks_name == NULL || strcmp(ksp->ks_name, ks_name) == 0))
54
+ return ksp;
55
+ }
56
+
57
+ errno = ENOENT;
58
+ return NULL;
59
+ }
60
+
61
+ int sigar_os_open(sigar_t **sig)
62
+ {
63
+ kstat_ctl_t *kc;
64
+ kstat_t *ksp;
65
+ sigar_t *sigar;
66
+ int i, status;
67
+ struct utsname name;
68
+ char *ptr;
69
+
70
+ sigar = malloc(sizeof(*sigar));
71
+ *sig = sigar;
72
+
73
+ sigar->log_level = -1; /* log nothing by default */
74
+ sigar->log_impl = NULL;
75
+ sigar->log_data = NULL;
76
+
77
+ uname(&name);
78
+ if ((ptr = strchr(name.release, '.'))) {
79
+ ptr++;
80
+ sigar->solaris_version = atoi(ptr);
81
+ }
82
+ else {
83
+ sigar->solaris_version = 6;
84
+ }
85
+
86
+ if ((ptr = getenv("SIGAR_USE_UCB_PS"))) {
87
+ sigar->use_ucb_ps = strEQ(ptr, "true");
88
+ }
89
+ else {
90
+ struct stat sb;
91
+ if (stat(SIGAR_USR_UCB_PS, &sb) < 0) {
92
+ sigar->use_ucb_ps = 0;
93
+ }
94
+ else {
95
+ sigar->use_ucb_ps = 1;
96
+ }
97
+ }
98
+
99
+ sigar->pagesize = 0;
100
+ i = sysconf(_SC_PAGESIZE);
101
+ while ((i >>= 1) > 0) {
102
+ sigar->pagesize++;
103
+ }
104
+
105
+ sigar->ticks = sysconf(_SC_CLK_TCK);
106
+ sigar->kc = kc = kstat_open();
107
+
108
+ if (!kc) {
109
+ return errno;
110
+ }
111
+
112
+ sigar->cpulist.size = 0;
113
+ sigar->ncpu = 0;
114
+ sigar->ks.cpu = NULL;
115
+ sigar->ks.cpu_info = NULL;
116
+ sigar->ks.cpuid = NULL;
117
+ sigar->ks.lcpu = 0;
118
+
119
+ sigar->koffsets.system[0] = -1;
120
+ sigar->koffsets.mempages[0] = -1;
121
+ sigar->koffsets.syspages[0] = -1;
122
+
123
+ if ((status = sigar_get_kstats(sigar)) != SIGAR_OK) {
124
+ fprintf(stderr, "status=%d\n", status);
125
+ }
126
+
127
+ sigar->boot_time = 0;
128
+
129
+ if ((ksp = sigar->ks.system) &&
130
+ (kstat_read(kc, ksp, NULL) >= 0))
131
+ {
132
+ sigar_koffsets_init_system(sigar, ksp);
133
+
134
+ sigar->boot_time = kSYSTEM(KSTAT_SYSTEM_BOOT_TIME);
135
+ }
136
+
137
+ sigar->last_pid = -1;
138
+ sigar->pinfo = NULL;
139
+
140
+ sigar->plib = NULL;
141
+ sigar->pgrab = NULL;
142
+ sigar->pfree = NULL;
143
+ sigar->pobjname = NULL;
144
+
145
+ sigar->pargs = NULL;
146
+
147
+ SIGAR_ZERO(&sigar->mib2);
148
+ sigar->mib2.sd = -1;
149
+
150
+ return SIGAR_OK;
151
+ }
152
+
153
+ int sigar_os_close(sigar_t *sigar)
154
+ {
155
+ kstat_close(sigar->kc);
156
+ if (sigar->mib2.sd != -1) {
157
+ close_mib2(&sigar->mib2);
158
+ }
159
+
160
+ if (sigar->ks.lcpu) {
161
+ free(sigar->ks.cpu);
162
+ free(sigar->ks.cpu_info);
163
+ free(sigar->ks.cpuid);
164
+ }
165
+ if (sigar->pinfo) {
166
+ free(sigar->pinfo);
167
+ }
168
+ if (sigar->cpulist.size != 0) {
169
+ sigar_cpu_list_destroy(sigar, &sigar->cpulist);
170
+ }
171
+ if (sigar->plib) {
172
+ dlclose(sigar->plib);
173
+ }
174
+ if (sigar->pargs) {
175
+ sigar_cache_destroy(sigar->pargs);
176
+ }
177
+ free(sigar);
178
+ return SIGAR_OK;
179
+ }
180
+
181
+ char *sigar_os_error_string(sigar_t *sigar, int err)
182
+ {
183
+ switch (err) {
184
+ case SIGAR_EMIB2:
185
+ return sigar->mib2.errmsg;
186
+ default:
187
+ return NULL;
188
+ }
189
+ }
190
+
191
+ int sigar_mem_get(sigar_t *sigar, sigar_mem_t *mem)
192
+ {
193
+ kstat_ctl_t *kc = sigar->kc;
194
+ kstat_t *ksp;
195
+ sigar_uint64_t kern = 0;
196
+
197
+ SIGAR_ZERO(mem);
198
+
199
+ /* XXX: is mem hot swappable or can we just do this during open ? */
200
+ mem->total = sysconf(_SC_PHYS_PAGES);
201
+ mem->total <<= sigar->pagesize;
202
+
203
+ if (sigar_kstat_update(sigar) == -1) {
204
+ return errno;
205
+ }
206
+
207
+ if ((ksp = sigar->ks.syspages) && kstat_read(kc, ksp, NULL) >= 0) {
208
+ sigar_koffsets_init_syspages(sigar, ksp);
209
+
210
+ mem->free = kSYSPAGES(KSTAT_SYSPAGES_FREE);
211
+ mem->free <<= sigar->pagesize;
212
+
213
+ mem->used = mem->total - mem->free;
214
+ }
215
+
216
+ if ((ksp = sigar->ks.mempages) && kstat_read(kc, ksp, NULL) >= 0) {
217
+ sigar_koffsets_init_mempages(sigar, ksp);
218
+ }
219
+
220
+ /* XXX mdb ::memstat cachelist/freelist not available to kstat, see: */
221
+ /* http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6821980 */
222
+
223
+ /* ZFS ARC cache. see: http://opensolaris.org/jive/thread.jspa?messageID=393695 */
224
+ if ((ksp = kstat_lookup(sigar->kc, "zfs", 0, "arcstats")) &&
225
+ (kstat_read(sigar->kc, ksp, NULL) != -1))
226
+ {
227
+ kstat_named_t *kn;
228
+
229
+ if ((kn = (kstat_named_t *)kstat_data_lookup(ksp, "size"))) {
230
+ kern = kn->value.i64;
231
+ }
232
+ if ((kn = (kstat_named_t *)kstat_data_lookup(ksp, "c_min"))) {
233
+ /* c_min cannot be reclaimed they say */
234
+ if (kern > kn->value.i64) {
235
+ kern -= kn->value.i64;
236
+ }
237
+ }
238
+ }
239
+
240
+ mem->actual_free = mem->free + kern;
241
+ mem->actual_used = mem->used - kern;
242
+
243
+ sigar_mem_calc_ram(sigar, mem);
244
+
245
+ return SIGAR_OK;
246
+ }
247
+
248
+ int sigar_swap_get(sigar_t *sigar, sigar_swap_t *swap)
249
+ {
250
+ kstat_t *ksp;
251
+ kstat_named_t *kn;
252
+ swaptbl_t *stab;
253
+ int num, i;
254
+ char path[PATH_MAX+1]; /* {un,re}used */
255
+
256
+ /* see: man swapctl(2) */
257
+ if ((num = swapctl(SC_GETNSWP, NULL)) == -1) {
258
+ return errno;
259
+ }
260
+
261
+ stab = malloc(num * sizeof(stab->swt_ent[0]) + sizeof(*stab));
262
+
263
+ stab->swt_n = num;
264
+ for (i=0; i<num; i++) {
265
+ stab->swt_ent[i].ste_path = path;
266
+ }
267
+
268
+ if ((num = swapctl(SC_LIST, stab)) == -1) {
269
+ free(stab);
270
+ return errno;
271
+ }
272
+
273
+ num = num < stab->swt_n ? num : stab->swt_n;
274
+ swap->total = swap->free = 0;
275
+ for (i=0; i<num; i++) {
276
+ if (stab->swt_ent[i].ste_flags & ST_INDEL) {
277
+ continue; /* swap file is being deleted */
278
+ }
279
+ swap->total += stab->swt_ent[i].ste_pages;
280
+ swap->free += stab->swt_ent[i].ste_free;
281
+ }
282
+ free(stab);
283
+
284
+ swap->total <<= sigar->pagesize;
285
+ swap->free <<= sigar->pagesize;
286
+ swap->used = swap->total - swap->free;
287
+
288
+ if (sigar_kstat_update(sigar) == -1) {
289
+ return errno;
290
+ }
291
+ if (!(ksp = kstat_lookup(sigar->kc, "cpu", -1, "vm"))) {
292
+ swap->page_in = swap->page_out = SIGAR_FIELD_NOTIMPL;
293
+ return SIGAR_OK;
294
+ }
295
+
296
+ swap->page_in = swap->page_out = 0;
297
+
298
+ /* XXX: these stats do not exist in this form on solaris 8 or 9.
299
+ * they are in the raw cpu_stat struct, but thats not
300
+ * binary compatible
301
+ */
302
+ do {
303
+ if (kstat_read(sigar->kc, ksp, NULL) < 0) {
304
+ break;
305
+ }
306
+
307
+ if ((kn = (kstat_named_t *)kstat_data_lookup(ksp, "pgin"))) {
308
+ swap->page_in += kn->value.i64; /* vmstat -s | grep "page ins" */
309
+ }
310
+ if ((kn = (kstat_named_t *)kstat_data_lookup(ksp, "pgout"))) {
311
+ swap->page_out += kn->value.i64; /* vmstat -s | grep "page outs" */
312
+ }
313
+ } while ((ksp = kstat_next(ksp, "cpu", -1, "vm")));
314
+
315
+ return SIGAR_OK;
316
+ }
317
+
318
+ #ifndef KSTAT_NAMED_STR_PTR
319
+ /* same offset as KSTAT_NAMED_STR_PTR(brand) */
320
+ #define KSTAT_NAMED_STR_PTR(n) (char *)((n)->value.i32)
321
+ #endif
322
+
323
+ static int get_chip_brand(sigar_t *sigar, int processor,
324
+ sigar_cpu_info_t *info)
325
+ {
326
+ kstat_t *ksp = sigar->ks.cpu_info[processor];
327
+ kstat_named_t *brand;
328
+
329
+ if (sigar->solaris_version < 10) {
330
+ /* don't bother; doesn't exist. */
331
+ return 0;
332
+ }
333
+
334
+ if (ksp &&
335
+ (kstat_read(sigar->kc, ksp, NULL) != -1) &&
336
+ (brand = (kstat_named_t *)kstat_data_lookup(ksp, "brand")))
337
+ {
338
+ char *name = KSTAT_NAMED_STR_PTR(brand);
339
+
340
+ char *vendor = "Sun";
341
+ char *vendors[] = {
342
+ "Intel", "AMD", NULL
343
+ };
344
+ int i;
345
+
346
+ if (!name) {
347
+ return 0;
348
+ }
349
+
350
+ for (i=0; vendors[i]; i++) {
351
+ if (strstr(name, vendors[i])) {
352
+ vendor = vendors[i];
353
+ break;
354
+ }
355
+ }
356
+
357
+ SIGAR_SSTRCPY(info->vendor, vendor);
358
+ #if 0
359
+ SIGAR_SSTRCPY(info->model, name);
360
+ sigar_cpu_model_adjust(sigar, info);
361
+ #endif
362
+ return 1;
363
+ }
364
+ else {
365
+ return 0;
366
+ }
367
+ }
368
+
369
+ static void free_chip_id(void *ptr)
370
+ {
371
+ /*noop*/
372
+ }
373
+
374
+ static int get_chip_id(sigar_t *sigar, int processor)
375
+ {
376
+ kstat_t *ksp = sigar->ks.cpu_info[processor];
377
+ kstat_named_t *chipid;
378
+
379
+ if (ksp &&
380
+ (kstat_read(sigar->kc, ksp, NULL) != -1) &&
381
+ (chipid = (kstat_named_t *)kstat_data_lookup(ksp, "chip_id")))
382
+ {
383
+ return chipid->value.i32;
384
+ }
385
+ else {
386
+ return -1;
387
+ }
388
+ }
389
+
390
+ int sigar_cpu_get(sigar_t *sigar, sigar_cpu_t *cpu)
391
+ {
392
+ int status, i;
393
+
394
+ status = sigar_cpu_list_get(sigar, &sigar->cpulist);
395
+
396
+ if (status != SIGAR_OK) {
397
+ return status;
398
+ }
399
+
400
+ SIGAR_ZERO(cpu);
401
+
402
+ for (i=0; i<sigar->cpulist.number; i++) {
403
+ sigar_cpu_t *xcpu = &sigar->cpulist.data[i];
404
+
405
+ cpu->user += xcpu->user;
406
+ cpu->sys += xcpu->sys;
407
+ cpu->idle += xcpu->idle;
408
+ cpu->nice += xcpu->nice;
409
+ cpu->wait += xcpu->wait;
410
+ cpu->total += xcpu->total;
411
+ }
412
+
413
+ return SIGAR_OK;
414
+ }
415
+
416
+ int sigar_cpu_list_get(sigar_t *sigar, sigar_cpu_list_t *cpulist)
417
+ {
418
+ kstat_ctl_t *kc = sigar->kc;
419
+ kstat_t *ksp;
420
+ uint_t cpuinfo[CPU_STATES];
421
+ unsigned int i;
422
+ int is_debug = SIGAR_LOG_IS_DEBUG(sigar);
423
+ sigar_cache_t *chips;
424
+
425
+ if (sigar_kstat_update(sigar) == -1) {
426
+ return errno;
427
+ }
428
+
429
+ if (cpulist == &sigar->cpulist) {
430
+ if (sigar->cpulist.size == 0) {
431
+ /* create once */
432
+ sigar_cpu_list_create(cpulist);
433
+ }
434
+ else {
435
+ /* reset, re-using cpulist.data */
436
+ sigar->cpulist.number = 0;
437
+ }
438
+ }
439
+ else {
440
+ sigar_cpu_list_create(cpulist);
441
+ }
442
+
443
+ if (is_debug) {
444
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
445
+ "[cpu_list] OS reports %d CPUs",
446
+ sigar->ncpu);
447
+ }
448
+
449
+ chips = sigar_cache_new(16);
450
+ chips->free_value = free_chip_id;
451
+
452
+ for (i=0; i<sigar->ncpu; i++) {
453
+ sigar_cpu_t *cpu;
454
+ char *buf;
455
+ int chip_id;
456
+ sigar_cache_entry_t *ent;
457
+
458
+ if (!CPU_ONLINE(sigar->ks.cpuid[i])) {
459
+ sigar_log_printf(sigar, SIGAR_LOG_INFO,
460
+ "cpu %d (id=%d) is offline",
461
+ i, sigar->ks.cpuid[i]);
462
+ continue;
463
+ }
464
+
465
+ if (!(ksp = sigar->ks.cpu[i])) {
466
+ sigar_log_printf(sigar, SIGAR_LOG_ERROR,
467
+ "NULL ksp for cpu %d (id=%d)",
468
+ i, sigar->ks.cpuid[i]);
469
+ continue; /* shouldnot happen */
470
+ }
471
+
472
+ if (kstat_read(kc, ksp, NULL) < 0) {
473
+ sigar_log_printf(sigar, SIGAR_LOG_ERROR,
474
+ "kstat_read failed for cpu %d (id=%d): %s",
475
+ i, sigar->ks.cpuid[i],
476
+ sigar_strerror(sigar, errno));
477
+ continue; /* shouldnot happen */
478
+ }
479
+
480
+ /*
481
+ * cpu_stat_t is not binary compatible between solaris versions.
482
+ * since cpu_stat is a 'raw' kstat and not 'named' we cannot
483
+ * use name based lookups as we do for others.
484
+ * the start of the cpu_stat_t structure is binary compatible,
485
+ * which looks like so:
486
+ * typedef struct cpu_stat {
487
+ * kmutex_t cpu_stat_lock;
488
+ * cpu_sysinfo_t cpu_sysinfo;
489
+ * ...
490
+ * typedef struct cpu_sysinfo {
491
+ * ulong cpu[CPU_STATES];
492
+ * ...
493
+ * we just copy the piece we need below:
494
+ */
495
+ buf = ksp->ks_data;
496
+ buf += sizeof(kmutex_t);
497
+ memcpy(&cpuinfo[0], buf, sizeof(cpuinfo));
498
+ chip_id = sigar->cpu_list_cores ? -1 : get_chip_id(sigar, i);
499
+
500
+ if (chip_id == -1) {
501
+ SIGAR_CPU_LIST_GROW(cpulist);
502
+ cpu = &cpulist->data[cpulist->number++];
503
+ SIGAR_ZERO(cpu);
504
+ }
505
+ else {
506
+ /* merge times of logical processors */
507
+ ent = sigar_cache_get(chips, chip_id);
508
+ if (ent->value) {
509
+ cpu = &cpulist->data[(long)ent->value-1];
510
+ }
511
+ else {
512
+ SIGAR_CPU_LIST_GROW(cpulist);
513
+ cpu = &cpulist->data[cpulist->number++];
514
+ ent->value = (void *)(long)cpulist->number;
515
+ SIGAR_ZERO(cpu);
516
+
517
+ if (is_debug) {
518
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
519
+ "[cpu_list] Merging times of"
520
+ " logical processors for chip_id=%d",
521
+ chip_id);
522
+ }
523
+ }
524
+ }
525
+
526
+ cpu->user += SIGAR_TICK2MSEC(cpuinfo[CPU_USER]);
527
+ cpu->sys += SIGAR_TICK2MSEC(cpuinfo[CPU_KERNEL]);
528
+ cpu->idle += SIGAR_TICK2MSEC(cpuinfo[CPU_IDLE]);
529
+ cpu->wait += SIGAR_TICK2MSEC(cpuinfo[CPU_WAIT]);
530
+ cpu->nice += 0; /* no cpu->nice */
531
+ cpu->total = cpu->user + cpu->sys + cpu->idle + cpu->wait;
532
+ }
533
+
534
+ sigar_cache_destroy(chips);
535
+
536
+ return SIGAR_OK;
537
+ }
538
+
539
+ int sigar_uptime_get(sigar_t *sigar,
540
+ sigar_uptime_t *uptime)
541
+ {
542
+ if (sigar->boot_time) {
543
+ uptime->uptime = time(NULL) - sigar->boot_time;
544
+ }
545
+ else {
546
+ uptime->uptime = 0; /* XXX: shouldn't happen */
547
+ }
548
+
549
+ return SIGAR_OK;
550
+ }
551
+
552
+ static int loadavg_keys[] = {
553
+ KSTAT_SYSTEM_LOADAVG_1,
554
+ KSTAT_SYSTEM_LOADAVG_2,
555
+ KSTAT_SYSTEM_LOADAVG_3
556
+ };
557
+
558
+ int sigar_loadavg_get(sigar_t *sigar,
559
+ sigar_loadavg_t *loadavg)
560
+ {
561
+ kstat_t *ksp;
562
+ int i;
563
+
564
+ if (sigar_kstat_update(sigar) == -1) {
565
+ return errno;
566
+ }
567
+
568
+ if (!(ksp = sigar->ks.system)) {
569
+ return -1;
570
+ }
571
+
572
+ if (kstat_read(sigar->kc, ksp, NULL) < 0) {
573
+ return -1;
574
+ }
575
+
576
+ sigar_koffsets_init_system(sigar, ksp);
577
+
578
+ for (i=0; i<3; i++) {
579
+ loadavg->loadavg[i] = (double)kSYSTEM(loadavg_keys[i]) / FSCALE;
580
+ }
581
+
582
+ return SIGAR_OK;
583
+ }
584
+
585
+ #define LIBPROC "/usr/lib/libproc.so"
586
+
587
+ #define CHECK_PSYM(s) \
588
+ if (!sigar->s) { \
589
+ sigar_log_printf(sigar, SIGAR_LOG_WARN, \
590
+ "[%s] Symbol not found: %s", \
591
+ SIGAR_FUNC, #s); \
592
+ dlclose(sigar->plib); \
593
+ sigar->plib = NULL; \
594
+ return SIGAR_ENOTIMPL; \
595
+ }
596
+
597
+ static char *proc_readlink(const char *name, char *buffer, size_t size)
598
+ {
599
+ int len;
600
+
601
+ if ((len = readlink(name, buffer, size-1)) < 0) {
602
+ return NULL;
603
+ }
604
+
605
+ buffer[len] = '\0';
606
+ return buffer;
607
+ }
608
+
609
+ static int sigar_init_libproc(sigar_t *sigar)
610
+ {
611
+ if (sigar->plib) {
612
+ return SIGAR_OK;
613
+ }
614
+
615
+ /* libproc.so ships with 5.8+ */
616
+ /* interface is undocumented, see libproc.h in the sun jdk sources */
617
+ sigar->plib = dlopen(LIBPROC, RTLD_LAZY);
618
+
619
+ if (!sigar->plib) {
620
+ sigar_log_printf(sigar, SIGAR_LOG_WARN,
621
+ "[%s] dlopen(%s) = %s",
622
+ SIGAR_FUNC, LIBPROC, dlerror());
623
+ return SIGAR_ENOTIMPL;
624
+ }
625
+
626
+ sigar->pgrab = (proc_grab_func_t)dlsym(sigar->plib, "Pgrab");
627
+ sigar->pfree = (proc_free_func_t)dlsym(sigar->plib, "Pfree");
628
+ sigar->pcreate_agent = (proc_create_agent_func_t)dlsym(sigar->plib, "Pcreate_agent");
629
+ sigar->pdestroy_agent = (proc_destroy_agent_func_t)dlsym(sigar->plib, "Pdestroy_agent");
630
+ sigar->pobjname = (proc_objname_func_t)dlsym(sigar->plib, "Pobjname");
631
+ sigar->pexename = (proc_exename_func_t)dlsym(sigar->plib, "Pexecname");
632
+ sigar->pdirname = (proc_dirname_func_t)dlsym(sigar->plib, "proc_dirname");
633
+ sigar->pfstat64 = (proc_fstat64_func_t)dlsym(sigar->plib, "pr_fstat64");
634
+ sigar->pgetsockopt = (proc_getsockopt_func_t)dlsym(sigar->plib, "pr_getsockopt");
635
+ sigar->pgetsockname = (proc_getsockname_func_t)dlsym(sigar->plib, "pr_getsockname");
636
+
637
+ CHECK_PSYM(pgrab);
638
+ CHECK_PSYM(pfree);
639
+ CHECK_PSYM(pobjname);
640
+
641
+ return SIGAR_OK;
642
+ }
643
+
644
+ /* from libproc.h, not included w/ solaris distro */
645
+ /* Error codes from Pgrab(), Pfgrab_core(), and Pgrab_core() */
646
+ #define G_STRANGE -1 /* Unanticipated error, errno is meaningful */
647
+ #define G_NOPROC 1 /* No such process */
648
+ #define G_NOCORE 2 /* No such core file */
649
+ #define G_NOPROCORCORE 3 /* No such proc or core (for proc_arg_grab) */
650
+ #define G_NOEXEC 4 /* Cannot locate executable file */
651
+ #define G_ZOMB 5 /* Zombie process */
652
+ #define G_PERM 6 /* No permission */
653
+ #define G_BUSY 7 /* Another process has control */
654
+ #define G_SYS 8 /* System process */
655
+ #define G_SELF 9 /* Process is self */
656
+ #define G_INTR 10 /* Interrupt received while grabbing */
657
+ #define G_LP64 11 /* Process is _LP64, self is ILP32 */
658
+ #define G_FORMAT 12 /* File is not an ELF format core file */
659
+ #define G_ELF 13 /* Libelf error, elf_errno() is meaningful */
660
+ #define G_NOTE 14 /* Required PT_NOTE Phdr not present in core */
661
+
662
+ static int sigar_pgrab(sigar_t *sigar, sigar_pid_t pid,
663
+ const char *func,
664
+ struct ps_prochandle **phandle)
665
+ {
666
+ int pstatus;
667
+
668
+ if (!(*phandle = sigar->pgrab(pid, 0x01, &pstatus))) {
669
+ switch (pstatus) {
670
+ case G_NOPROC:
671
+ return ESRCH;
672
+ case G_PERM:
673
+ return EACCES;
674
+ default:
675
+ sigar_log_printf(sigar, SIGAR_LOG_ERROR,
676
+ "[%s] Pgrab error=%d",
677
+ func, pstatus);
678
+ return ENOTSUP; /*XXX*/
679
+ }
680
+ }
681
+
682
+ return SIGAR_OK;
683
+ }
684
+
685
+ int sigar_os_proc_list_get(sigar_t *sigar,
686
+ sigar_proc_list_t *proclist)
687
+ {
688
+ return sigar_proc_list_procfs_get(sigar, proclist);
689
+ }
690
+
691
+ int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
692
+ sigar_proc_mem_t *procmem)
693
+ {
694
+ int status = sigar_proc_psinfo_get(sigar, pid);
695
+ psinfo_t *pinfo = sigar->pinfo;
696
+ prusage_t usage;
697
+
698
+ if (status != SIGAR_OK) {
699
+ return status;
700
+ }
701
+
702
+ procmem->size = pinfo->pr_size << 10;
703
+ procmem->resident = pinfo->pr_rssize << 10;
704
+ procmem->share = SIGAR_FIELD_NOTIMPL;
705
+
706
+ if (sigar_proc_usage_get(sigar, &usage, pid) == SIGAR_OK) {
707
+ procmem->minor_faults = usage.pr_minf;
708
+ procmem->major_faults = usage.pr_majf;
709
+ procmem->page_faults =
710
+ procmem->minor_faults +
711
+ procmem->major_faults;
712
+ }
713
+ else {
714
+ procmem->minor_faults = SIGAR_FIELD_NOTIMPL;
715
+ procmem->major_faults = SIGAR_FIELD_NOTIMPL;
716
+ procmem->page_faults = SIGAR_FIELD_NOTIMPL;
717
+ }
718
+
719
+ return SIGAR_OK;
720
+ }
721
+
722
+ int sigar_proc_cumulative_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
723
+ sigar_proc_cumulative_disk_io_t *proc_cumulative_disk_io)
724
+ {
725
+ prusage_t usage;
726
+ int status;
727
+ if ((status = sigar_proc_usage_get(sigar, &usage, pid)) != SIGAR_OK) {
728
+ return status;
729
+ }
730
+ proc_cumulative_disk_io->bytes_read = SIGAR_FIELD_NOTIMPL;
731
+ proc_cumulative_disk_io->bytes_written = SIGAR_FIELD_NOTIMPL;
732
+ proc_cumulative_disk_io->bytes_total = usage.pr_ioch;
733
+
734
+ return SIGAR_OK;
735
+ }
736
+
737
+ int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid,
738
+ sigar_proc_cred_t *proccred)
739
+ {
740
+ int status = sigar_proc_psinfo_get(sigar, pid);
741
+ psinfo_t *pinfo = sigar->pinfo;
742
+
743
+ if (status != SIGAR_OK) {
744
+ return status;
745
+ }
746
+
747
+ proccred->uid = pinfo->pr_uid;
748
+ proccred->gid = pinfo->pr_gid;
749
+ proccred->euid = pinfo->pr_euid;
750
+ proccred->egid = pinfo->pr_egid;
751
+
752
+ return SIGAR_OK;
753
+ }
754
+
755
+ #define TIMESTRUCT_2MSEC(t) \
756
+ ((t.tv_sec * MILLISEC) + (t.tv_nsec / (NANOSEC/MILLISEC)))
757
+
758
+ int sigar_proc_time_get(sigar_t *sigar, sigar_pid_t pid,
759
+ sigar_proc_time_t *proctime)
760
+ {
761
+ prusage_t usage;
762
+ int status;
763
+
764
+ if ((status = sigar_proc_usage_get(sigar, &usage, pid)) != SIGAR_OK) {
765
+ return status;
766
+ }
767
+
768
+ proctime->start_time = usage.pr_create.tv_sec + sigar->boot_time;
769
+ proctime->start_time *= MILLISEC;
770
+
771
+ if (usage.pr_utime.tv_sec < 0) {
772
+ /* XXX wtf? seen on solaris 10, only for the self process */
773
+ pstatus_t pstatus;
774
+
775
+ status = sigar_proc_status_get(sigar, &pstatus, pid);
776
+ if (status != SIGAR_OK) {
777
+ return status;
778
+ }
779
+
780
+ usage.pr_utime.tv_sec = pstatus.pr_utime.tv_sec;
781
+ usage.pr_utime.tv_nsec = pstatus.pr_utime.tv_nsec;
782
+ usage.pr_stime.tv_sec = pstatus.pr_stime.tv_sec;
783
+ usage.pr_stime.tv_nsec = pstatus.pr_stime.tv_nsec;
784
+ }
785
+
786
+ proctime->user = TIMESTRUCT_2MSEC(usage.pr_utime);
787
+ proctime->sys = TIMESTRUCT_2MSEC(usage.pr_stime);
788
+ proctime->total = proctime->user + proctime->sys;
789
+
790
+ return SIGAR_OK;
791
+ }
792
+
793
+ int sigar_proc_state_get(sigar_t *sigar, sigar_pid_t pid,
794
+ sigar_proc_state_t *procstate)
795
+ {
796
+ int status = sigar_proc_psinfo_get(sigar, pid);
797
+ psinfo_t *pinfo = sigar->pinfo;
798
+
799
+ if (status != SIGAR_OK) {
800
+ return status;
801
+ }
802
+
803
+ SIGAR_SSTRCPY(procstate->name, pinfo->pr_fname);
804
+ procstate->ppid = pinfo->pr_ppid;
805
+ procstate->tty = pinfo->pr_ttydev;
806
+ procstate->priority = pinfo->pr_lwp.pr_pri;
807
+ procstate->nice = pinfo->pr_lwp.pr_nice - NZERO;
808
+ procstate->threads = pinfo->pr_nlwp;
809
+ procstate->processor = pinfo->pr_lwp.pr_onpro;
810
+
811
+ switch (pinfo->pr_lwp.pr_state) {
812
+ case SONPROC:
813
+ case SRUN:
814
+ procstate->state = 'R';
815
+ break;
816
+ case SZOMB:
817
+ procstate->state = 'Z';
818
+ break;
819
+ case SSLEEP:
820
+ procstate->state = 'S';
821
+ break;
822
+ case SSTOP:
823
+ procstate->state = 'T';
824
+ break;
825
+ case SIDL:
826
+ procstate->state = 'D';
827
+ break;
828
+ }
829
+
830
+ return SIGAR_OK;
831
+ }
832
+
833
+ typedef struct {
834
+ int timestamp;
835
+ char *args;
836
+ } pargs_t;
837
+
838
+ static void pargs_free(void *value)
839
+ {
840
+ pargs_t *pargs = (pargs_t *)value;
841
+ if (pargs->args != NULL) {
842
+ free(pargs->args);
843
+ }
844
+ free(pargs);
845
+ }
846
+
847
+ static int ucb_ps_args_get(sigar_t *sigar, sigar_pid_t pid,
848
+ sigar_proc_args_t *procargs,
849
+ int timestamp)
850
+ {
851
+ char buffer[9086], *args=NULL, *arg;
852
+ sigar_cache_entry_t *ent;
853
+ FILE *fp;
854
+ pargs_t *pargs;
855
+
856
+ if (!sigar->pargs) {
857
+ sigar->pargs = sigar_cache_new(15);
858
+ sigar->pargs->free_value = pargs_free;
859
+ }
860
+
861
+ ent = sigar_cache_get(sigar->pargs, pid);
862
+ if (ent->value) {
863
+ pargs = (pargs_t *)ent->value;
864
+ if (pargs->timestamp != timestamp) {
865
+ if (pargs->args) {
866
+ free(pargs->args);
867
+ pargs->args = NULL;
868
+ }
869
+ }
870
+ }
871
+ else {
872
+ pargs = malloc(sizeof(*pargs));
873
+ pargs->args = NULL;
874
+ ent->value = pargs;
875
+ }
876
+
877
+ pargs->timestamp = timestamp;
878
+
879
+ if (pargs->args) {
880
+ args = pargs->args;
881
+ }
882
+ else {
883
+ snprintf(buffer, sizeof(buffer),
884
+ SIGAR_USR_UCB_PS " -ww %ld", (long)pid);
885
+
886
+ if (!(fp = popen(buffer, "r"))) {
887
+ return errno;
888
+ }
889
+ /* skip header */
890
+ (void)fgets(buffer, sizeof(buffer), fp);
891
+ if ((args = fgets(buffer, sizeof(buffer), fp))) {
892
+ int len;
893
+
894
+ /* skip PID,TT,S,TIME */
895
+ args = sigar_skip_multiple_token(args, 4);
896
+ SIGAR_SKIP_SPACE(args);
897
+ len = strlen(args);
898
+ if (len > 0) {
899
+ args[len-1] = '\0'; /* chop \n */
900
+ }
901
+
902
+ pargs->args = malloc(len+1);
903
+ memcpy(pargs->args, args, len);
904
+ }
905
+
906
+ pclose(fp);
907
+
908
+ if (!args) {
909
+ return ESRCH;
910
+ }
911
+ }
912
+
913
+ while (*args && (arg = sigar_getword(&args, ' '))) {
914
+ SIGAR_PROC_ARGS_GROW(procargs);
915
+ procargs->data[procargs->number++] = arg;
916
+ }
917
+
918
+ return SIGAR_OK;
919
+ }
920
+
921
+ int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid,
922
+ sigar_proc_args_t *procargs)
923
+ {
924
+ psinfo_t *pinfo;
925
+ int fd, status;
926
+ char buffer[9086];
927
+ char *argvb[56];
928
+ char **argvp = argvb;
929
+
930
+ int n;
931
+ size_t nread = 0;
932
+ unsigned int argv_size;
933
+
934
+ if ((status = sigar_proc_psinfo_get(sigar, pid)) != SIGAR_OK) {
935
+ return status;
936
+ }
937
+ pinfo = sigar->pinfo;
938
+
939
+ if (pinfo->pr_argc == 0) {
940
+ procargs->number = 0;
941
+ return SIGAR_OK;
942
+ }
943
+ else if (pinfo->pr_dmodel != PR_MODEL_NATIVE) {
944
+ /* we are compiled in 32bit mode
945
+ * punt any 64bit native process,
946
+ * sizeof our structures can't handle.
947
+ */
948
+ if (sigar->use_ucb_ps) {
949
+ return ucb_ps_args_get(sigar, pid, procargs,
950
+ pinfo->pr_start.tv_sec);
951
+ }
952
+ else {
953
+ return ENOTSUP;
954
+ }
955
+ }
956
+
957
+ argv_size = sizeof(*argvp) * pinfo->pr_argc;
958
+
959
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/as");
960
+
961
+ if ((fd = open(buffer, O_RDONLY)) < 0) {
962
+ if ((errno == EACCES) && sigar->use_ucb_ps) {
963
+ return ucb_ps_args_get(sigar, pid, procargs,
964
+ pinfo->pr_start.tv_sec);
965
+ }
966
+ else {
967
+ return PROC_ERRNO;
968
+ }
969
+ }
970
+
971
+ if (argv_size > sizeof(argvb)) {
972
+ argvp = malloc(argv_size);
973
+ }
974
+
975
+ if ((nread = pread(fd, argvp, argv_size, pinfo->pr_argv)) <= 0) {
976
+ close(fd);
977
+ if (argvp != argvb) {
978
+ free(argvp);
979
+ }
980
+ return errno;
981
+ }
982
+
983
+ for (n = 0; n < pinfo->pr_argc; n++) {
984
+ int alen;
985
+ char *arg;
986
+
987
+ if ((nread = pread(fd, buffer, sizeof(buffer)-1, (off_t)argvp[n])) <= 0) {
988
+ close(fd);
989
+ if (argvp != argvb) {
990
+ free(argvp);
991
+ }
992
+ return errno;
993
+ }
994
+
995
+ buffer[nread] = '\0';
996
+ alen = strlen(buffer)+1;
997
+ arg = malloc(alen);
998
+ memcpy(arg, buffer, alen);
999
+
1000
+ SIGAR_PROC_ARGS_GROW(procargs);
1001
+ procargs->data[procargs->number++] = arg;
1002
+ }
1003
+
1004
+ if (argvp != argvb) {
1005
+ free(argvp);
1006
+ }
1007
+
1008
+ close(fd);
1009
+
1010
+ return SIGAR_OK;
1011
+ }
1012
+
1013
+ int sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid,
1014
+ sigar_proc_env_t *procenv)
1015
+ {
1016
+ psinfo_t *pinfo;
1017
+ int fd, status;
1018
+ char buffer[BUFSIZ], *offsets[512];
1019
+ size_t nread;
1020
+ int n=0, max=sizeof(offsets)/sizeof(char *);
1021
+
1022
+ if ((status = sigar_proc_psinfo_get(sigar, pid)) != SIGAR_OK) {
1023
+ return status;
1024
+ }
1025
+ pinfo = sigar->pinfo;
1026
+
1027
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/as");
1028
+
1029
+ if ((fd = open(buffer, O_RDONLY)) < 0) {
1030
+ return PROC_ERRNO;
1031
+ }
1032
+
1033
+ if ((nread = pread(fd, offsets, sizeof(offsets),
1034
+ pinfo->pr_envp)) <= 0)
1035
+ {
1036
+ close(fd);
1037
+ return errno;
1038
+ }
1039
+
1040
+ while ((n < max) && offsets[n]) {
1041
+ char *val;
1042
+ int klen, vlen, status;
1043
+ char key[128]; /* XXX is there a max key size? */
1044
+
1045
+ if ((nread = pread(fd, buffer, sizeof(buffer),
1046
+ (off_t)offsets[n++])) <= 0)
1047
+ {
1048
+ close(fd);
1049
+ return errno;
1050
+ }
1051
+
1052
+ val = strchr(buffer, '=');
1053
+
1054
+ if (val == NULL) {
1055
+ break; /*XXX*/
1056
+ }
1057
+
1058
+ klen = val - buffer;
1059
+ SIGAR_SSTRCPY(key, buffer);
1060
+ key[klen] = '\0';
1061
+ ++val;
1062
+
1063
+ vlen = strlen(val);
1064
+
1065
+ status = procenv->env_getter(procenv->data,
1066
+ key, klen, val, vlen);
1067
+
1068
+ if (status != SIGAR_OK) {
1069
+ /* not an error; just stop iterating */
1070
+ break;
1071
+ }
1072
+ }
1073
+
1074
+ close(fd);
1075
+
1076
+ return SIGAR_OK;
1077
+ }
1078
+
1079
+ int sigar_proc_fd_get(sigar_t *sigar, sigar_pid_t pid,
1080
+ sigar_proc_fd_t *procfd)
1081
+ {
1082
+ int status =
1083
+ sigar_proc_fd_count(sigar, pid, &procfd->total);
1084
+
1085
+ return status;
1086
+ }
1087
+
1088
+ static int sigar_proc_path_exe_get(sigar_t *sigar, sigar_pid_t pid,
1089
+ sigar_proc_exe_t *procexe)
1090
+ {
1091
+ /* solaris 10+ */
1092
+ char buffer[BUFSIZ];
1093
+
1094
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/path/a.out");
1095
+ if (!proc_readlink(buffer, procexe->name, sizeof(procexe->name))) {
1096
+ procexe->name[0] = '\0';
1097
+ }
1098
+
1099
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/path/cwd");
1100
+ if (!proc_readlink(buffer, procexe->cwd, sizeof(procexe->cwd))) {
1101
+ procexe->cwd[0] = '\0';
1102
+ }
1103
+
1104
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/path/root");
1105
+ if (!proc_readlink(buffer, procexe->root, sizeof(procexe->root))) {
1106
+ procexe->root[0] = '\0';
1107
+ }
1108
+
1109
+ return SIGAR_OK;
1110
+ }
1111
+
1112
+ static int proc_module_get_exe(void *data, char *name, int len)
1113
+ {
1114
+ sigar_proc_exe_t *procexe = (sigar_proc_exe_t *)data;
1115
+ SIGAR_STRNCPY(procexe->name, name, sizeof(procexe->name));
1116
+ return !SIGAR_OK; /* break loop */
1117
+ }
1118
+
1119
+ static int sigar_which_exe_get(sigar_t *sigar, sigar_proc_exe_t *procexe)
1120
+ {
1121
+ char *path = getenv("PATH");
1122
+ char exe[PATH_MAX];
1123
+ if (path == NULL) {
1124
+ return EINVAL;
1125
+ }
1126
+
1127
+ while (path) {
1128
+ char *ptr = strchr(path, ':');
1129
+ if (!ptr) {
1130
+ break;
1131
+ }
1132
+ exe[0] = '\0';
1133
+ strncat(exe, path, ptr-path);
1134
+ strncat(exe, "/", 1);
1135
+ strcat(exe, procexe->name);
1136
+ if (access(exe, X_OK) == 0) {
1137
+ SIGAR_STRNCPY(procexe->name, exe, sizeof(procexe->name));
1138
+ break;
1139
+ }
1140
+ path = ptr+1;
1141
+ }
1142
+
1143
+ return ENOENT;
1144
+ }
1145
+
1146
+ int sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid,
1147
+ sigar_proc_exe_t *procexe)
1148
+ {
1149
+ int status;
1150
+ char buffer[BUFSIZ];
1151
+ struct ps_prochandle *phandle;
1152
+
1153
+ if (sigar->solaris_version >= 10) {
1154
+ return sigar_proc_path_exe_get(sigar, pid, procexe);
1155
+ }
1156
+
1157
+ if ((status = sigar_init_libproc(sigar)) != SIGAR_OK) {
1158
+ return status;
1159
+ }
1160
+
1161
+ procexe->name[0] = '\0';
1162
+
1163
+ /* Pgrab would return G_SELF error */
1164
+ if (pid == sigar_pid_get(sigar)) {
1165
+ sigar_proc_modules_t procmods;
1166
+ procmods.module_getter = proc_module_get_exe;
1167
+ procmods.data = procexe;
1168
+
1169
+ status =
1170
+ sigar_dlinfo_modules(sigar, &procmods);
1171
+ if (status == SIGAR_OK) {
1172
+ if (procexe->name[0] != '/') {
1173
+ sigar_which_exe_get(sigar, procexe);
1174
+ }
1175
+ }
1176
+ }
1177
+ else {
1178
+ status = sigar_pgrab(sigar, pid, SIGAR_FUNC, &phandle);
1179
+
1180
+ if (status == SIGAR_OK) {
1181
+ sigar->pexename(phandle, procexe->name, sizeof(procexe->name));
1182
+ sigar->pfree(phandle);
1183
+ }
1184
+ }
1185
+
1186
+ if (procexe->name[0] == '\0') {
1187
+ /*XXX*/
1188
+ }
1189
+
1190
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/cwd");
1191
+
1192
+ if (!sigar->pdirname(buffer, procexe->cwd, sizeof(procexe->cwd))) {
1193
+ procexe->cwd[0] = '\0';
1194
+ }
1195
+
1196
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/root");
1197
+
1198
+ if (!(sigar->pdirname(buffer, procexe->root, sizeof(procexe->root)))) {
1199
+ procexe->root[0] = '\0';
1200
+ }
1201
+
1202
+ return SIGAR_OK;
1203
+ }
1204
+
1205
+ static int sigar_read_xmaps(sigar_t *sigar,
1206
+ prxmap_t *xmaps, int total,
1207
+ unsigned long *last_inode,
1208
+ struct ps_prochandle *phandle,
1209
+ sigar_proc_modules_t *procmods)
1210
+ {
1211
+ int status, i;
1212
+ unsigned long inode;
1213
+ char buffer[BUFSIZ];
1214
+
1215
+ for (i=0; i<total; i++) {
1216
+ if (xmaps[i].pr_mflags & MA_ANON) {
1217
+ continue; /* heap, stack, etc */
1218
+ }
1219
+
1220
+ inode = xmaps[i].pr_ino;
1221
+
1222
+ if ((inode == 0) || (inode == *last_inode)) {
1223
+ *last_inode = 0;
1224
+ continue;
1225
+ }
1226
+
1227
+ *last_inode = inode;
1228
+
1229
+ sigar->pobjname(phandle, xmaps[i].pr_vaddr, buffer, sizeof(buffer));
1230
+
1231
+ status =
1232
+ procmods->module_getter(procmods->data, buffer, strlen(buffer));
1233
+
1234
+ if (status != SIGAR_OK) {
1235
+ /* not an error; just stop iterating */
1236
+ return status;
1237
+ }
1238
+ }
1239
+
1240
+ return SIGAR_OK;
1241
+ }
1242
+
1243
+ static int sigar_pgrab_modules(sigar_t *sigar, sigar_pid_t pid,
1244
+ sigar_proc_modules_t *procmods)
1245
+ {
1246
+ int fd, pstatus;
1247
+ off_t map_size, nread;
1248
+ unsigned long last_inode = 0;
1249
+ prxmap_t xmaps[15]; /* ~2K */
1250
+ struct ps_prochandle *phandle;
1251
+ struct stat statbuf;
1252
+ char buffer[BUFSIZ];
1253
+
1254
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/xmap");
1255
+
1256
+ if ((fd = open(buffer, O_RDONLY)) < 0) {
1257
+ return errno;
1258
+ }
1259
+
1260
+ if (fstat(fd, &statbuf) < 0) {
1261
+ close(fd);
1262
+ return errno;
1263
+ }
1264
+
1265
+ map_size = statbuf.st_size;
1266
+
1267
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
1268
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
1269
+ "[%s] pid=%d, size=%d",
1270
+ SIGAR_FUNC, pid, map_size);
1271
+ }
1272
+
1273
+ if ((pstatus = sigar_init_libproc(sigar)) != SIGAR_OK) {
1274
+ close(fd);
1275
+ return pstatus;
1276
+ }
1277
+
1278
+ pstatus = sigar_pgrab(sigar, pid, SIGAR_FUNC, &phandle);
1279
+
1280
+ if (pstatus != SIGAR_OK) {
1281
+ close(fd);
1282
+ return pstatus;
1283
+ }
1284
+
1285
+ for (nread=0; nread<statbuf.st_size; ) {
1286
+ off_t wanted = map_size > sizeof(xmaps) ? sizeof(xmaps) : map_size;
1287
+ int total = wanted / sizeof(prxmap_t);
1288
+
1289
+ if (pread(fd, xmaps, wanted, nread) != wanted) {
1290
+ close(fd);
1291
+ sigar->pfree(phandle);
1292
+ return errno;
1293
+ }
1294
+
1295
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
1296
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
1297
+ "[%s] nread=%d, map_size=%d, wanted=%d, total=%d",
1298
+ SIGAR_FUNC,
1299
+ nread, map_size, wanted, total);
1300
+ }
1301
+
1302
+ if (sigar_read_xmaps(sigar, xmaps, total,
1303
+ &last_inode,
1304
+ phandle, procmods) != SIGAR_OK)
1305
+ {
1306
+ break;
1307
+ }
1308
+
1309
+ nread += wanted;
1310
+ map_size -= wanted;
1311
+ }
1312
+
1313
+ close(fd);
1314
+
1315
+ sigar->pfree(phandle);
1316
+
1317
+ return SIGAR_OK;
1318
+ }
1319
+
1320
+ int sigar_proc_modules_get(sigar_t *sigar, sigar_pid_t pid,
1321
+ sigar_proc_modules_t *procmods)
1322
+ {
1323
+ if (pid == sigar_pid_get(sigar)) {
1324
+ /* Pgrab would return G_SELF, this is faster anyhow */
1325
+ /* XXX one difference to Pgrab, first entry is not the exe name */
1326
+ return sigar_dlinfo_modules(sigar, procmods);
1327
+ }
1328
+ else {
1329
+ return sigar_pgrab_modules(sigar, pid, procmods);
1330
+ }
1331
+ }
1332
+
1333
+ #define TIME_NSEC(t) \
1334
+ (SIGAR_SEC2NANO((t).tv_sec) + (sigar_uint64_t)(t).tv_nsec)
1335
+
1336
+ int sigar_thread_cpu_get(sigar_t *sigar,
1337
+ sigar_uint64_t id,
1338
+ sigar_thread_cpu_t *cpu)
1339
+ {
1340
+ struct lwpinfo info;
1341
+
1342
+ if (id != 0) {
1343
+ return SIGAR_ENOTIMPL;
1344
+ }
1345
+
1346
+ _lwp_info(&info);
1347
+
1348
+ cpu->user = TIME_NSEC(info.lwp_utime);
1349
+ cpu->sys = TIME_NSEC(info.lwp_stime);
1350
+ cpu->total = TIME_NSEC(info.lwp_utime) + TIME_NSEC(info.lwp_stime);
1351
+
1352
+ return SIGAR_OK;
1353
+ }
1354
+
1355
+ #include <sys/mnttab.h>
1356
+
1357
+ int sigar_os_fs_type_get(sigar_file_system_t *fsp)
1358
+ {
1359
+ char *type = fsp->sys_type_name;
1360
+
1361
+ switch (*type) {
1362
+ case 'u':
1363
+ if (strEQ(type, "ufs")) {
1364
+ fsp->type = SIGAR_FSTYPE_LOCAL_DISK;
1365
+ }
1366
+ break;
1367
+ /* XXX */
1368
+ }
1369
+
1370
+ return fsp->type;
1371
+ }
1372
+
1373
+ int sigar_file_system_list_get(sigar_t *sigar,
1374
+ sigar_file_system_list_t *fslist)
1375
+ {
1376
+ struct mnttab ent;
1377
+ sigar_file_system_t *fsp;
1378
+ FILE *fp = fopen(MNTTAB, "r");
1379
+
1380
+ if (!fp) {
1381
+ return errno;
1382
+ }
1383
+
1384
+ sigar_file_system_list_create(fslist);
1385
+
1386
+ while (getmntent(fp, &ent) == 0) {
1387
+ if (strstr(ent.mnt_mntopts, "ignore")) {
1388
+ continue; /* e.g. vold */
1389
+ }
1390
+
1391
+ SIGAR_FILE_SYSTEM_LIST_GROW(fslist);
1392
+
1393
+ fsp = &fslist->data[fslist->number++];
1394
+
1395
+ SIGAR_SSTRCPY(fsp->dir_name, ent.mnt_mountp);
1396
+ SIGAR_SSTRCPY(fsp->dev_name, ent.mnt_special);
1397
+ SIGAR_SSTRCPY(fsp->sys_type_name, ent.mnt_fstype);
1398
+ SIGAR_SSTRCPY(fsp->options, ent.mnt_mntopts);
1399
+ sigar_fs_type_init(fsp);
1400
+ }
1401
+
1402
+ fclose(fp);
1403
+
1404
+ return SIGAR_OK;
1405
+ }
1406
+
1407
+ typedef struct {
1408
+ char device[PATH_MAX];
1409
+ char name[8];
1410
+ int instance;
1411
+ } fsdev_path_t;
1412
+
1413
+ typedef struct {
1414
+ char name[256];
1415
+ int is_partition;
1416
+ sigar_disk_usage_t disk;
1417
+ } iodev_t;
1418
+
1419
+ static fsdev_path_t *get_fsdev_paths(sigar_t *sigar,
1420
+ sigar_file_system_list_t *fslist)
1421
+ {
1422
+ int i, ndisk, size;
1423
+ char buffer[BUFSIZ], *ptr;
1424
+ char *dev, *inst, *drv;
1425
+ fsdev_path_t *paths, *mapping;
1426
+ FILE *fp = fopen("/etc/path_to_inst", "r");
1427
+
1428
+ if (!fp) {
1429
+ return NULL;
1430
+ }
1431
+
1432
+ for (i=0, ndisk=0; i<fslist->number; i++) {
1433
+ sigar_file_system_t *fsp = &fslist->data[i];
1434
+ if (fsp->type == SIGAR_FSTYPE_LOCAL_DISK) {
1435
+ ndisk++;
1436
+ }
1437
+ }
1438
+
1439
+ size = sizeof(*paths) * (ndisk+1);
1440
+ mapping = paths = malloc(size);
1441
+ memset(mapping, '\0', size);
1442
+
1443
+ while ((ptr = fgets(buffer, sizeof(buffer), fp))) {
1444
+ /* eat dust java */
1445
+ char *q;
1446
+
1447
+ SIGAR_SKIP_SPACE(ptr);
1448
+ if (*ptr == '#') {
1449
+ continue;
1450
+ }
1451
+ if (*ptr == '"') {
1452
+ ptr++;
1453
+ }
1454
+ dev = ptr;
1455
+ if (!(q = strchr(ptr, '"'))) {
1456
+ continue;
1457
+ }
1458
+ ptr = q+1;
1459
+ *q = '\0';
1460
+ SIGAR_SKIP_SPACE(ptr);
1461
+ inst = ptr;
1462
+ while (sigar_isdigit(*ptr)) {
1463
+ ptr++;
1464
+ }
1465
+ *ptr = '\0';
1466
+ ptr++;
1467
+ SIGAR_SKIP_SPACE(ptr);
1468
+ if (*ptr == '"') {
1469
+ ptr++;
1470
+ }
1471
+ drv = ptr;
1472
+ if (!(q = strchr(ptr, '"'))) {
1473
+ continue;
1474
+ }
1475
+ *q = '\0';
1476
+
1477
+ if (!(strEQ(drv, "sd") ||
1478
+ strEQ(drv, "ssd") ||
1479
+ strEQ(drv, "st") ||
1480
+ strEQ(drv, "dad") ||
1481
+ strEQ(drv, "cmdk")))
1482
+ {
1483
+ continue;
1484
+ }
1485
+
1486
+ paths->instance = atoi(inst);
1487
+ if (!kstat_lookup(sigar->kc, drv, paths->instance, NULL)) {
1488
+ continue;
1489
+ }
1490
+
1491
+ SIGAR_SSTRCPY(paths->device, dev);
1492
+ SIGAR_SSTRCPY(paths->name, drv);
1493
+
1494
+ if (--ndisk < 0) {
1495
+ /* XXX prevent overflow */
1496
+ break;
1497
+ }
1498
+ paths++;
1499
+ }
1500
+ fclose(fp);
1501
+
1502
+ return mapping;
1503
+ }
1504
+
1505
+ static int create_fsdev_cache(sigar_t *sigar)
1506
+ {
1507
+ fsdev_path_t *paths, *mapping;
1508
+ sigar_file_system_list_t fslist;
1509
+ int i, j;
1510
+ int status;
1511
+ int debug = SIGAR_LOG_IS_DEBUG(sigar);
1512
+
1513
+ sigar->fsdev = sigar_cache_new(15);
1514
+
1515
+ status = sigar_file_system_list_get(sigar, &fslist);
1516
+
1517
+ if (status != SIGAR_OK) {
1518
+ return status;
1519
+ }
1520
+
1521
+ if (!(mapping = get_fsdev_paths(sigar, &fslist))) {
1522
+ sigar_file_system_list_destroy(sigar, &fslist);
1523
+ return ENOENT;
1524
+ }
1525
+
1526
+ for (i=0; i<fslist.number; i++) {
1527
+ sigar_file_system_t *fsp = &fslist.data[i];
1528
+
1529
+ if (fsp->type == SIGAR_FSTYPE_LOCAL_DISK) {
1530
+ char device[PATH_MAX+1], *ptr=device;
1531
+ int len = readlink(fsp->dev_name, device, sizeof(device)-1);
1532
+ char *s;
1533
+ char partition;
1534
+
1535
+ if (len < 0) {
1536
+ continue;
1537
+ }
1538
+ device[len] = '\0';
1539
+
1540
+ if (debug) {
1541
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG, "[fsdev] name=%s, dev=%s",
1542
+ fsp->dev_name, device);
1543
+ }
1544
+
1545
+ while (strnEQ(ptr, "../", 3)) {
1546
+ ptr += 3;
1547
+ }
1548
+ if (strnEQ(ptr, "devices", 7)) {
1549
+ ptr += 7;
1550
+ }
1551
+ if ((s = strchr(ptr, ':'))) {
1552
+ partition = *(s+1);
1553
+ }
1554
+ else {
1555
+ continue;
1556
+ }
1557
+
1558
+ for (j=0, paths=mapping; paths->name[0]; j++) {
1559
+ if (strnEQ(paths->device, ptr, strlen(paths->device))) {
1560
+ sigar_cache_entry_t *ent;
1561
+ struct stat sb;
1562
+ int retval = stat(fsp->dir_name, &sb);
1563
+ iodev_t *iodev;
1564
+
1565
+ if (retval == 0) {
1566
+ iodev = malloc(sizeof(*iodev));
1567
+
1568
+ SIGAR_DISK_STATS_INIT(&iodev->disk);
1569
+ /* e.g. sd9,g
1570
+ * module == sd
1571
+ * instance == 9
1572
+ * partition == 8
1573
+ */
1574
+ snprintf(iodev->name, sizeof(iodev->name), "%s%d,%c",
1575
+ paths->name, paths->instance, partition);
1576
+
1577
+ ent = sigar_cache_get(sigar->fsdev, SIGAR_FSDEV_ID(sb));
1578
+ ent->value = iodev;
1579
+
1580
+ if (debug) {
1581
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
1582
+ "[fsdev] map %s -> %s",
1583
+ fsp->dir_name, iodev->name);
1584
+ }
1585
+ }
1586
+ break;
1587
+ }
1588
+ paths++;
1589
+ }
1590
+ }
1591
+ }
1592
+
1593
+ free(mapping);
1594
+ sigar_file_system_list_destroy(sigar, &fslist);
1595
+
1596
+ return SIGAR_OK;
1597
+ }
1598
+
1599
+ static int io_kstat_read(sigar_t *sigar,
1600
+ sigar_disk_usage_t *disk,
1601
+ kstat_t *ksp)
1602
+ {
1603
+ kstat_io_t *io;
1604
+
1605
+ kstat_read(sigar->kc, ksp, NULL);
1606
+
1607
+ io = (kstat_io_t *)ksp->ks_data;
1608
+
1609
+ disk->reads = io->reads;
1610
+ disk->writes = io->writes;
1611
+ disk->read_bytes = io->nread;
1612
+ disk->write_bytes = io->nwritten;
1613
+ disk->qtime = io->wlentime;
1614
+ disk->rtime = io->rlentime;
1615
+ disk->wtime = io->wlentime;
1616
+ disk->time = disk->rtime + disk->wtime;
1617
+ disk->snaptime = ksp->ks_snaptime;
1618
+
1619
+ return SIGAR_OK;
1620
+ }
1621
+
1622
+
1623
+ static int sigar_kstat_disk_usage_get(sigar_t *sigar, const char *name,
1624
+ sigar_disk_usage_t *disk,
1625
+ kstat_t **kio)
1626
+ {
1627
+ kstat_t *ksp;
1628
+
1629
+ if (sigar_kstat_update(sigar) == -1) {
1630
+ return errno;
1631
+ }
1632
+
1633
+ for (ksp = sigar->kc->kc_chain;
1634
+ ksp;
1635
+ ksp = ksp->ks_next)
1636
+ {
1637
+ if (ksp->ks_type != KSTAT_TYPE_IO) {
1638
+ continue;
1639
+ }
1640
+ if (strEQ(ksp->ks_name, name)) {
1641
+ int status = io_kstat_read(sigar, disk, ksp);
1642
+ *kio = ksp;
1643
+ return status;
1644
+ }
1645
+ }
1646
+
1647
+ return ENXIO;
1648
+ }
1649
+
1650
+ static int simple_hash(const char *s)
1651
+ {
1652
+ int hash = 0;
1653
+ while (*s) {
1654
+ hash = 31*hash + *s++;
1655
+ }
1656
+ return hash;
1657
+ }
1658
+
1659
+ int sigar_disk_usage_get(sigar_t *sigar, const char *name,
1660
+ sigar_disk_usage_t *disk)
1661
+ {
1662
+ kstat_t *ksp;
1663
+ int status;
1664
+ iodev_t *iodev = NULL;
1665
+ sigar_cache_entry_t *ent;
1666
+ sigar_uint64_t id;
1667
+
1668
+ SIGAR_DISK_STATS_INIT(disk);
1669
+
1670
+ if (!sigar->fsdev) {
1671
+ if (create_fsdev_cache(sigar) != SIGAR_OK) {
1672
+ return SIGAR_OK;
1673
+ }
1674
+ }
1675
+
1676
+ if (*name == '/') {
1677
+ struct stat sb;
1678
+
1679
+ if (stat(name, &sb) < 0) {
1680
+ return errno;
1681
+ }
1682
+
1683
+ id = SIGAR_FSDEV_ID(sb);
1684
+ ent = sigar_cache_get(sigar->fsdev, id);
1685
+ if (ent->value == NULL) {
1686
+ return ENXIO;
1687
+ }
1688
+ iodev = (iodev_t *)ent->value;
1689
+
1690
+ status = sigar_kstat_disk_usage_get(sigar, iodev->name, disk, &ksp);
1691
+ }
1692
+ else {
1693
+ status = sigar_kstat_disk_usage_get(sigar, name, disk, &ksp);
1694
+ if (status != SIGAR_OK) {
1695
+ return status;
1696
+ }
1697
+ id = simple_hash(name); /*XXX*/
1698
+ ent = sigar_cache_get(sigar->fsdev, id);
1699
+ if (ent->value) {
1700
+ iodev = (iodev_t *)ent->value;
1701
+ }
1702
+ else {
1703
+ ent->value = iodev = malloc(sizeof(*iodev));
1704
+ SIGAR_SSTRCPY(iodev->name, name);
1705
+ SIGAR_DISK_STATS_INIT(&iodev->disk);
1706
+ }
1707
+ }
1708
+
1709
+ /* service_time formula derived from opensolaris.org:iostat.c */
1710
+ if ((status == SIGAR_OK) && iodev) {
1711
+ sigar_uint64_t delta;
1712
+ double avw, avr, tps, mtps;
1713
+ double etime, hr_etime;
1714
+
1715
+ if (iodev->disk.snaptime) {
1716
+ delta = disk->snaptime - iodev->disk.snaptime;
1717
+ }
1718
+ else {
1719
+ delta = ksp->ks_crtime - ksp->ks_snaptime;
1720
+ }
1721
+
1722
+ hr_etime = (double)delta;
1723
+ if (hr_etime == 0.0) {
1724
+ hr_etime = (double)NANOSEC;
1725
+ }
1726
+ etime = hr_etime / (double)NANOSEC;
1727
+
1728
+ tps =
1729
+ (((double)(disk->reads - iodev->disk.reads)) / etime) +
1730
+ (((double)(disk->writes - iodev->disk.writes)) / etime);
1731
+
1732
+ delta = disk->wtime - iodev->disk.wtime;
1733
+ if (delta) {
1734
+ avw = (double)delta;
1735
+ avw /= hr_etime;
1736
+ }
1737
+ else {
1738
+ avw = 0.0;
1739
+ }
1740
+
1741
+ delta = disk->rtime - iodev->disk.rtime;
1742
+ if (delta) {
1743
+ avr = (double)delta;
1744
+ avr /= hr_etime;
1745
+ }
1746
+ else {
1747
+ avr = 0.0;
1748
+ }
1749
+
1750
+ disk->queue = avw;
1751
+ disk->service_time = 0.0;
1752
+
1753
+ if (tps && (avw != 0.0 || avr != 0.0)) {
1754
+ mtps = 1000.0 / tps;
1755
+ if (avw != 0.0) {
1756
+ disk->service_time += avw * mtps;
1757
+ }
1758
+ if (avr != 0.0) {
1759
+ disk->service_time += avr * mtps;
1760
+ }
1761
+ }
1762
+
1763
+ memcpy(&iodev->disk, disk, sizeof(iodev->disk));
1764
+ }
1765
+
1766
+ return status;
1767
+ }
1768
+
1769
+ int sigar_file_system_usage_get(sigar_t *sigar,
1770
+ const char *dirname,
1771
+ sigar_file_system_usage_t *fsusage)
1772
+ {
1773
+ int status = sigar_statvfs(sigar, dirname, fsusage);
1774
+
1775
+ if (status != SIGAR_OK) {
1776
+ return status;
1777
+ }
1778
+
1779
+ fsusage->use_percent = sigar_file_system_usage_calc_used(sigar, fsusage);
1780
+
1781
+ sigar_disk_usage_get(sigar, dirname, &fsusage->disk);
1782
+
1783
+ return SIGAR_OK;
1784
+ }
1785
+
1786
+ int sigar_cpu_info_list_get(sigar_t *sigar,
1787
+ sigar_cpu_info_list_t *cpu_infos)
1788
+ {
1789
+ processor_info_t stats;
1790
+ unsigned int i;
1791
+ int status = SIGAR_OK;
1792
+ int brand = -1;
1793
+ sigar_cache_t *chips;
1794
+ int is_debug = SIGAR_LOG_IS_DEBUG(sigar);
1795
+ int nsockets = 0;
1796
+
1797
+ if (sigar_kstat_update(sigar) == -1) { /* for sigar->ncpu */
1798
+ return errno;
1799
+ }
1800
+
1801
+ /*
1802
+ * stats we care about will be the same for each
1803
+ * online processor, so just grab the first.
1804
+ */
1805
+ for (i=0; i<sigar->ncpu; i++) {
1806
+ processorid_t id = sigar->ks.cpuid[i];
1807
+
1808
+ if ((status = processor_info(id, &stats)) < 0) {
1809
+ continue;
1810
+ }
1811
+ else {
1812
+ status = SIGAR_OK;
1813
+ break;
1814
+ }
1815
+ }
1816
+
1817
+ if (status != SIGAR_OK) {
1818
+ /* should never happen */
1819
+ return ENOENT;
1820
+ }
1821
+
1822
+ sigar_cpu_info_list_create(cpu_infos);
1823
+ chips = sigar_cache_new(16);
1824
+ chips->free_value = free_chip_id;
1825
+
1826
+ for (i=0; i<sigar->ncpu; i++) {
1827
+ sigar_cpu_info_t *info;
1828
+ int chip_id = get_chip_id(sigar, i);
1829
+
1830
+ if (chip_id != -1) {
1831
+ sigar_cache_entry_t *ent =
1832
+ sigar_cache_get(chips, chip_id);
1833
+
1834
+ if (ent->value) {
1835
+ if (!sigar->cpu_list_cores) {
1836
+ continue;
1837
+ }
1838
+ }
1839
+ else {
1840
+ ++nsockets;
1841
+ ent->value = chips; /*anything non-NULL*/
1842
+ if (is_debug) {
1843
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
1844
+ "[cpu_list] Merging info of"
1845
+ " logical processors for chip_id=%d",
1846
+ chip_id);
1847
+ }
1848
+ }
1849
+ }
1850
+ else {
1851
+ ++nsockets;
1852
+ }
1853
+
1854
+ SIGAR_CPU_INFO_LIST_GROW(cpu_infos);
1855
+
1856
+ info = &cpu_infos->data[cpu_infos->number++];
1857
+
1858
+ SIGAR_SSTRCPY(info->model, stats.pi_processor_type);
1859
+
1860
+ if (brand == -1) {
1861
+ brand = get_chip_brand(sigar, i, info);
1862
+ }
1863
+
1864
+ if (strEQ(info->model, "i386")) {
1865
+ if (!brand) {
1866
+ /* assume Intel on x86 */
1867
+ SIGAR_SSTRCPY(info->vendor, "Intel");
1868
+ }
1869
+ SIGAR_SSTRCPY(info->model, "x86");
1870
+ }
1871
+ else {
1872
+ if (!brand) {
1873
+ /* assume Sun */
1874
+ SIGAR_SSTRCPY(info->vendor, "Sun");
1875
+ }
1876
+ /* s/sparc/Sparc/ */
1877
+ info->model[0] = toupper(info->model[0]);
1878
+ }
1879
+
1880
+ if (brand) {
1881
+ SIGAR_SSTRCPY(info->vendor, cpu_infos->data[0].vendor);
1882
+ }
1883
+
1884
+ info->mhz = stats.pi_clock;
1885
+ info->cache_size = SIGAR_FIELD_NOTIMPL; /*XXX*/
1886
+ }
1887
+
1888
+ sigar_cache_destroy(chips);
1889
+
1890
+ for (i=0; i<cpu_infos->number; i++) {
1891
+ sigar_cpu_info_t *info = &cpu_infos->data[i];
1892
+ info->total_sockets = nsockets;
1893
+ info->total_cores = sigar->ncpu;
1894
+ info->cores_per_socket = sigar->ncpu / nsockets;
1895
+ }
1896
+
1897
+ return SIGAR_OK;
1898
+ }
1899
+
1900
+ int sigar_net_route_list_get(sigar_t *sigar,
1901
+ sigar_net_route_list_t *routelist)
1902
+
1903
+ {
1904
+ char *data;
1905
+ int len, rc;
1906
+ struct opthdr *op;
1907
+ size_t nread=0, size=0;
1908
+ const char *size_from;
1909
+
1910
+ sigar_net_route_list_create(routelist);
1911
+
1912
+ while ((rc = get_mib2(&sigar->mib2, &op, &data, &len)) == GET_MIB2_OK) {
1913
+ mib2_ipRouteEntry_t *entry;
1914
+ char *end;
1915
+
1916
+ if (op->level != MIB2_IP) {
1917
+ continue;
1918
+ }
1919
+
1920
+ if (op->name == 0) {
1921
+ /* we want to use this size for bincompat */
1922
+ size = ((mib2_ip_t *)data)->ipRouteEntrySize;
1923
+ continue;
1924
+ }
1925
+ else if (op->name != MIB2_IP_21) {
1926
+ continue;
1927
+ }
1928
+
1929
+ if (size == 0) {
1930
+ size_from = "sizeof";
1931
+ size = sizeof(*entry);
1932
+ }
1933
+ else {
1934
+ size_from = "mib2_ip";
1935
+ }
1936
+
1937
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
1938
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
1939
+ "[route_list] ipRouteEntrySize=%d (from %s)",
1940
+ size, size_from);
1941
+ }
1942
+
1943
+ for (entry = (mib2_ipRouteEntry_t *)data, end = data + len;
1944
+ (char *)entry < end;
1945
+ nread+=size, entry = (mib2_ipRouteEntry_t *)((char *)data+nread))
1946
+ {
1947
+ sigar_net_route_t *route;
1948
+ int type = entry->ipRouteInfo.re_ire_type;
1949
+
1950
+ /* filter same as netstat -r */
1951
+ if ((type == IRE_CACHE) ||
1952
+ (type == IRE_BROADCAST) ||
1953
+ (type == IRE_LOCAL))
1954
+ {
1955
+ continue;
1956
+ }
1957
+
1958
+ SIGAR_NET_ROUTE_LIST_GROW(routelist);
1959
+ route = &routelist->data[routelist->number++];
1960
+
1961
+ sigar_net_address_set(route->destination,
1962
+ entry->ipRouteDest);
1963
+
1964
+ sigar_net_address_set(route->gateway,
1965
+ entry->ipRouteNextHop);
1966
+
1967
+ sigar_net_address_set(route->mask,
1968
+ entry->ipRouteMask);
1969
+
1970
+ route->refcnt = entry->ipRouteInfo.re_ref;
1971
+ route->irtt = entry->ipRouteInfo.re_rtt;
1972
+ route->metric = entry->ipRouteMetric1;
1973
+
1974
+ SIGAR_SSTRCPY(route->ifname, entry->ipRouteIfIndex.o_bytes);
1975
+
1976
+ route->flags = RTF_UP;
1977
+ if ((route->destination.addr.in == 0) &&
1978
+ (route->mask.addr.in == 0))
1979
+ {
1980
+ route->flags |= RTF_GATEWAY;
1981
+ }
1982
+
1983
+ route->use = route->window = route->mtu =
1984
+ SIGAR_FIELD_NOTIMPL; /*XXX*/
1985
+ }
1986
+ }
1987
+
1988
+ if (rc != GET_MIB2_EOD) {
1989
+ close_mib2(&sigar->mib2);
1990
+ return SIGAR_EMIB2;
1991
+ }
1992
+
1993
+ return SIGAR_OK;
1994
+ }
1995
+
1996
+ static void ifstat_kstat_common(sigar_net_interface_stat_t *ifstat,
1997
+ kstat_named_t *data, int ndata)
1998
+ {
1999
+ int i;
2000
+
2001
+ for (i=0; i<ndata; i++) {
2002
+ sigar_uint64_t value = data[i].value.KSTAT_UINT;
2003
+
2004
+ char *ptr = data[i].name;
2005
+
2006
+ switch (*ptr) {
2007
+ case 'c':
2008
+ if (strEQ(ptr, "collisions")) {
2009
+ ifstat->tx_collisions = value;
2010
+ }
2011
+ break;
2012
+ case 'd':
2013
+ if (strEQ(ptr, "drop")) {
2014
+ ifstat->rx_dropped = value;
2015
+ ifstat->tx_dropped = value;
2016
+ }
2017
+ break;
2018
+ case 'i':
2019
+ if (strEQ(ptr, "ipackets")) {
2020
+ if (ifstat->rx_packets == 0) {
2021
+ ifstat->rx_packets = value;
2022
+ }
2023
+ }
2024
+ else if (strEQ(ptr, "ipackets64")) {
2025
+ ifstat->rx_packets = data[i].value.ui64;
2026
+ }
2027
+ else if (strEQ(ptr, "ierrors")) {
2028
+ ifstat->rx_errors = value;
2029
+ }
2030
+ else if (strEQ(ptr, "ifspeed")) {
2031
+ ifstat->speed = value;
2032
+ }
2033
+ break;
2034
+ case 'f':
2035
+ if (strEQ(ptr, "framing")) {
2036
+ ifstat->rx_frame = value;
2037
+ }
2038
+ break;
2039
+ case 'm':
2040
+ if (strEQ(ptr, "missed")) {
2041
+ ifstat->rx_dropped = value;
2042
+ ifstat->tx_dropped = value;
2043
+ }
2044
+ break;
2045
+ case 'n':
2046
+ if (strEQ(ptr, "nocarrier")) {
2047
+ ifstat->tx_carrier = value;
2048
+ }
2049
+ break;
2050
+ case 'o':
2051
+ if (strEQ(ptr, "obytes")) {
2052
+ if (ifstat->tx_bytes == 0) {
2053
+ ifstat->tx_bytes = value;
2054
+ }
2055
+ }
2056
+ else if (strEQ(ptr, "obytes64")) {
2057
+ ifstat->tx_bytes = data[i].value.ui64;
2058
+ }
2059
+ else if (strEQ(ptr, "oerrors")) {
2060
+ ifstat->tx_errors = value;
2061
+ }
2062
+ else if (strEQ(ptr, "oflo")) {
2063
+ ifstat->tx_overruns = value;
2064
+ }
2065
+ else if (strEQ(ptr, "opackets")) {
2066
+ if (ifstat->tx_packets == 0) {
2067
+ ifstat->tx_packets = value;
2068
+ }
2069
+ }
2070
+ else if (strEQ(ptr, "opackets64")) {
2071
+ ifstat->tx_packets = data[i].value.ui64;
2072
+ }
2073
+ else if (strEQ(ptr, "toolong_errors")) {
2074
+ ifstat->tx_overruns = value;
2075
+ }
2076
+ break;
2077
+ case 'r':
2078
+ if (strEQ(ptr, "rbytes")) {
2079
+ if (ifstat->rx_bytes == 0) {
2080
+ ifstat->rx_bytes = value;
2081
+ }
2082
+ }
2083
+ else if (strEQ(ptr, "rbytes64")) {
2084
+ ifstat->rx_bytes = data[i].value.ui64;
2085
+ }
2086
+ else if (strEQ(ptr, "rx_overflow")) {
2087
+ ifstat->rx_overruns = value;
2088
+ }
2089
+ break;
2090
+ default:
2091
+ break;
2092
+ }
2093
+ }
2094
+ }
2095
+
2096
+ static int sigar_net_ifstat_get_any(sigar_t *sigar, const char *name,
2097
+ sigar_net_interface_stat_t *ifstat)
2098
+ {
2099
+ kstat_ctl_t *kc = sigar->kc;
2100
+ kstat_t *ksp;
2101
+ kstat_named_t *data;
2102
+
2103
+ if (sigar_kstat_update(sigar) == -1) {
2104
+ return errno;
2105
+ }
2106
+
2107
+ if (!(ksp = kstat_lookup(kc, NULL, -1, (char *)name))) {
2108
+ return ENXIO;
2109
+ }
2110
+
2111
+ if (kstat_read(kc, ksp, NULL) < 0) {
2112
+ return ENOENT;
2113
+ }
2114
+
2115
+ data = (kstat_named_t *)ksp->ks_data;
2116
+
2117
+ ifstat_kstat_common(ifstat, data, ksp->ks_ndata);
2118
+
2119
+ return SIGAR_OK;
2120
+ }
2121
+
2122
+ /* loopback interface only has rx/tx packets */
2123
+ static int sigar_net_ifstat_get_lo(sigar_t *sigar, const char *name,
2124
+ sigar_net_interface_stat_t *ifstat)
2125
+ {
2126
+ ifstat->rx_packets = 0;
2127
+ ifstat->rx_bytes = SIGAR_FIELD_NOTIMPL;
2128
+ ifstat->rx_errors = SIGAR_FIELD_NOTIMPL;
2129
+ ifstat->rx_dropped = SIGAR_FIELD_NOTIMPL;
2130
+ ifstat->rx_overruns = SIGAR_FIELD_NOTIMPL;
2131
+ ifstat->rx_frame = SIGAR_FIELD_NOTIMPL;
2132
+
2133
+ ifstat->tx_packets = 0;
2134
+ ifstat->tx_bytes = SIGAR_FIELD_NOTIMPL;
2135
+ ifstat->tx_errors = SIGAR_FIELD_NOTIMPL;
2136
+ ifstat->tx_dropped = SIGAR_FIELD_NOTIMPL;
2137
+ ifstat->tx_overruns = SIGAR_FIELD_NOTIMPL;
2138
+ ifstat->tx_collisions = SIGAR_FIELD_NOTIMPL;
2139
+ ifstat->tx_carrier = SIGAR_FIELD_NOTIMPL;
2140
+
2141
+ ifstat->speed = SIGAR_FIELD_NOTIMPL;
2142
+
2143
+ return sigar_net_ifstat_get_any(sigar, name, ifstat);
2144
+ }
2145
+
2146
+ int sigar_net_interface_stat_get(sigar_t *sigar, const char *name,
2147
+ sigar_net_interface_stat_t *ifstat)
2148
+ {
2149
+ ifstat->speed = SIGAR_FIELD_NOTIMPL;
2150
+
2151
+ if (strnEQ(name, "lo", 2)) {
2152
+ return sigar_net_ifstat_get_lo(sigar, name, ifstat);
2153
+ }
2154
+ else {
2155
+ SIGAR_ZERO(ifstat);
2156
+ return sigar_net_ifstat_get_any(sigar, name, ifstat);
2157
+ }
2158
+ }
2159
+
2160
+ int sigar_net_interface_ipv6_config_get(sigar_t *sigar, const char *name,
2161
+ sigar_net_interface_config_t *ifconfig)
2162
+ {
2163
+ int sock;
2164
+ struct lifreq lifr;
2165
+
2166
+ if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
2167
+ return errno;
2168
+ }
2169
+
2170
+ SIGAR_SSTRCPY(lifr.lifr_name, name);
2171
+
2172
+ if (ioctl(sock, SIOCGLIFADDR, &lifr) == 0) {
2173
+ struct in6_addr *addr = SIGAR_SIN6_ADDR(&lifr.lifr_addr);
2174
+
2175
+ sigar_net_address6_set(ifconfig->address6, addr);
2176
+ sigar_net_interface_scope6_set(ifconfig, addr);
2177
+ ifconfig->prefix6_length = lifr.lifr_addrlen;
2178
+ }
2179
+
2180
+ close(sock);
2181
+ return SIGAR_OK;
2182
+ }
2183
+
2184
+ #define TCPQ_SIZE(s) ((s) >= 0 ? (s) : 0)
2185
+
2186
+ static int tcp_connection_get(sigar_net_connection_walker_t *walker,
2187
+ struct mib2_tcpConnEntry *entry,
2188
+ int len)
2189
+ {
2190
+ int flags = walker->flags;
2191
+ int status;
2192
+ char *end = (char *)entry + len;
2193
+
2194
+ while ((char *)entry < end) {
2195
+ int state = entry->tcpConnEntryInfo.ce_state;
2196
+
2197
+ if (((flags & SIGAR_NETCONN_SERVER) && (state == TCPS_LISTEN)) ||
2198
+ ((flags & SIGAR_NETCONN_CLIENT) && (state != TCPS_LISTEN)))
2199
+ {
2200
+ sigar_net_connection_t conn;
2201
+
2202
+ SIGAR_ZERO(&conn);
2203
+
2204
+ sigar_net_address_set(conn.local_address, entry->tcpConnLocalAddress);
2205
+ sigar_net_address_set(conn.remote_address, entry->tcpConnRemAddress);
2206
+
2207
+ conn.local_port = entry->tcpConnLocalPort;
2208
+ conn.remote_port = entry->tcpConnRemPort;
2209
+ conn.type = SIGAR_NETCONN_TCP;
2210
+ conn.send_queue =
2211
+ TCPQ_SIZE(entry->tcpConnEntryInfo.ce_snxt -
2212
+ entry->tcpConnEntryInfo.ce_suna - 1);
2213
+ conn.receive_queue =
2214
+ TCPQ_SIZE(entry->tcpConnEntryInfo.ce_rnxt -
2215
+ entry->tcpConnEntryInfo.ce_rack);
2216
+
2217
+ switch (state) {
2218
+ case TCPS_CLOSED:
2219
+ conn.state = SIGAR_TCP_CLOSE;
2220
+ break;
2221
+ case TCPS_IDLE:
2222
+ conn.state = SIGAR_TCP_IDLE;
2223
+ break;
2224
+ case TCPS_BOUND:
2225
+ conn.state = SIGAR_TCP_BOUND;
2226
+ break;
2227
+ case TCPS_LISTEN:
2228
+ conn.state = SIGAR_TCP_LISTEN;
2229
+ break;
2230
+ case TCPS_SYN_SENT:
2231
+ conn.state = SIGAR_TCP_SYN_SENT;
2232
+ break;
2233
+ case TCPS_SYN_RCVD:
2234
+ conn.state = SIGAR_TCP_SYN_RECV;
2235
+ break;
2236
+ case TCPS_ESTABLISHED:
2237
+ conn.state = SIGAR_TCP_ESTABLISHED;
2238
+ break;
2239
+ case TCPS_CLOSE_WAIT:
2240
+ conn.state = SIGAR_TCP_CLOSE_WAIT;
2241
+ break;
2242
+ case TCPS_FIN_WAIT_1:
2243
+ conn.state = SIGAR_TCP_FIN_WAIT1;
2244
+ break;
2245
+ case TCPS_CLOSING:
2246
+ conn.state = SIGAR_TCP_CLOSING;
2247
+ break;
2248
+ case TCPS_LAST_ACK:
2249
+ conn.state = SIGAR_TCP_LAST_ACK;
2250
+ break;
2251
+ case TCPS_FIN_WAIT_2:
2252
+ conn.state = SIGAR_TCP_FIN_WAIT2;
2253
+ break;
2254
+ case TCPS_TIME_WAIT:
2255
+ conn.state = SIGAR_TCP_TIME_WAIT;
2256
+ break;
2257
+ default:
2258
+ conn.state = SIGAR_TCP_UNKNOWN;
2259
+ break;
2260
+ }
2261
+
2262
+ status = walker->add_connection(walker, &conn);
2263
+ if (status != SIGAR_OK) {
2264
+ return status;
2265
+ }
2266
+ }
2267
+
2268
+ entry++;
2269
+ }
2270
+
2271
+ return SIGAR_OK;
2272
+ }
2273
+
2274
+ static int udp_connection_get(sigar_net_connection_walker_t *walker,
2275
+ struct mib2_udpEntry *entry,
2276
+ int len)
2277
+ {
2278
+ int flags = walker->flags;
2279
+ int status;
2280
+ char *end = (char *)entry + len;
2281
+
2282
+ while ((char *)entry < end) {
2283
+ int state = entry->udpEntryInfo.ue_state;
2284
+
2285
+ /* XXX dunno if this state check is right */
2286
+ if (((flags & SIGAR_NETCONN_SERVER) && (state == MIB2_UDP_idle)) ||
2287
+ ((flags & SIGAR_NETCONN_CLIENT) && (state != MIB2_UDP_idle)))
2288
+ {
2289
+ sigar_net_connection_t conn;
2290
+
2291
+ SIGAR_ZERO(&conn);
2292
+
2293
+ sigar_net_address_set(conn.local_address, entry->udpLocalAddress);
2294
+ sigar_net_address_set(conn.remote_address, 0);
2295
+
2296
+ conn.local_port = entry->udpLocalPort;
2297
+ conn.remote_port = 0;
2298
+ conn.type = SIGAR_NETCONN_UDP;
2299
+
2300
+ status = walker->add_connection(walker, &conn);
2301
+ if (status != SIGAR_OK) {
2302
+ return status;
2303
+ }
2304
+ }
2305
+
2306
+ entry++;
2307
+ }
2308
+
2309
+ return SIGAR_OK;
2310
+ }
2311
+
2312
+ int sigar_net_connection_walk(sigar_net_connection_walker_t *walker)
2313
+ {
2314
+ sigar_t *sigar = walker->sigar;
2315
+ int flags = walker->flags;
2316
+ int status;
2317
+ int want_tcp = flags & SIGAR_NETCONN_TCP;
2318
+ int want_udp = flags & SIGAR_NETCONN_UDP;
2319
+ char *data;
2320
+ int len;
2321
+ int rc;
2322
+ struct opthdr *op;
2323
+
2324
+ while ((rc = get_mib2(&sigar->mib2, &op, &data, &len)) == GET_MIB2_OK) {
2325
+ if ((op->level == MIB2_TCP) &&
2326
+ (op->name == MIB2_TCP_13) &&
2327
+ want_tcp)
2328
+ {
2329
+ status =
2330
+ tcp_connection_get(walker,
2331
+ (struct mib2_tcpConnEntry *)data,
2332
+ len);
2333
+ }
2334
+ else if ((op->level == MIB2_UDP) &&
2335
+ (op->name == MIB2_UDP_5) &&
2336
+ want_udp)
2337
+ {
2338
+ status =
2339
+ udp_connection_get(walker,
2340
+ (struct mib2_udpEntry *)data,
2341
+ len);
2342
+ }
2343
+ else {
2344
+ status = SIGAR_OK;
2345
+ }
2346
+
2347
+ if (status != SIGAR_OK) {
2348
+ break;
2349
+ }
2350
+ }
2351
+
2352
+ if (rc != GET_MIB2_EOD) {
2353
+ close_mib2(&sigar->mib2);
2354
+ return SIGAR_EMIB2;
2355
+ }
2356
+
2357
+ return SIGAR_OK;
2358
+ }
2359
+
2360
+ SIGAR_DECLARE(int)
2361
+ sigar_tcp_get(sigar_t *sigar,
2362
+ sigar_tcp_t *tcp)
2363
+ {
2364
+ char *data;
2365
+ int len;
2366
+ int rc;
2367
+ struct opthdr *op;
2368
+ mib2_tcp_t *mib = NULL;
2369
+
2370
+ while ((rc = get_mib2(&sigar->mib2, &op, &data, &len)) == GET_MIB2_OK) {
2371
+ if ((op->level == MIB2_TCP) && (op->name == 0)) {
2372
+ mib = (mib2_tcp_t *)data;
2373
+ break;
2374
+ }
2375
+ }
2376
+
2377
+ if (mib) {
2378
+ tcp->active_opens = mib->tcpActiveOpens;
2379
+ tcp->passive_opens = mib->tcpPassiveOpens;
2380
+ tcp->attempt_fails = mib->tcpAttemptFails;
2381
+ tcp->estab_resets = mib->tcpEstabResets;
2382
+ tcp->curr_estab = mib->tcpCurrEstab;
2383
+ tcp->in_segs = mib->tcpInSegs;
2384
+ tcp->out_segs = mib->tcpOutSegs;
2385
+ tcp->retrans_segs = mib->tcpRetransSegs;
2386
+ tcp->in_errs = SIGAR_FIELD_NOTIMPL; /* XXX mib2_ip_t.tcpInErrs */
2387
+ tcp->out_rsts = mib->tcpOutRsts;
2388
+ return SIGAR_OK;
2389
+ }
2390
+ else {
2391
+ return SIGAR_ENOTIMPL;
2392
+ }
2393
+ }
2394
+
2395
+ static int sigar_nfs_get(sigar_t *sigar,
2396
+ char *type,
2397
+ char **names,
2398
+ char *nfs)
2399
+ {
2400
+ size_t offset;
2401
+ kstat_t *ksp;
2402
+ int i;
2403
+
2404
+ if (sigar_kstat_update(sigar) == -1) {
2405
+ return errno;
2406
+ }
2407
+
2408
+ if (!(ksp = kstat_lookup(sigar->kc, "nfs", 0, type))) {
2409
+ return SIGAR_ENOTIMPL;
2410
+ }
2411
+
2412
+ if (kstat_read(sigar->kc, ksp, NULL) < 0) {
2413
+ return errno;
2414
+ }
2415
+
2416
+ for (i=0, offset=0;
2417
+ names[i];
2418
+ i++, offset+=sizeof(sigar_uint64_t))
2419
+ {
2420
+ sigar_uint64_t val;
2421
+ kstat_named_t *kv =
2422
+ kstat_data_lookup(ksp, names[i]);
2423
+
2424
+ if (kv) {
2425
+ val = kv->value.ui64;
2426
+ }
2427
+ else {
2428
+ val = -1;
2429
+ }
2430
+
2431
+ *(sigar_uint64_t *)((char *)nfs + offset) = val;
2432
+ }
2433
+
2434
+ return SIGAR_OK;
2435
+ }
2436
+
2437
+ static char *nfs_v2_names[] = {
2438
+ "null",
2439
+ "getattr",
2440
+ "setattr",
2441
+ "root",
2442
+ "lookup",
2443
+ "readlink",
2444
+ "read",
2445
+ "wrcache",
2446
+ "write",
2447
+ "create",
2448
+ "remove",
2449
+ "rename",
2450
+ "link",
2451
+ "symlink",
2452
+ "mkdir",
2453
+ "rmdir",
2454
+ "readdir",
2455
+ "statfs",
2456
+ NULL
2457
+ };
2458
+
2459
+ int sigar_nfs_client_v2_get(sigar_t *sigar,
2460
+ sigar_nfs_client_v2_t *nfs)
2461
+ {
2462
+ return sigar_nfs_get(sigar, "rfsreqcnt_v2", nfs_v2_names, (char *)nfs);
2463
+ }
2464
+
2465
+ int sigar_nfs_server_v2_get(sigar_t *sigar,
2466
+ sigar_nfs_server_v2_t *nfs)
2467
+ {
2468
+ return sigar_nfs_get(sigar, "rfsproccnt_v2", nfs_v2_names, (char *)nfs);
2469
+ }
2470
+
2471
+ static char *nfs_v3_names[] = {
2472
+ "null",
2473
+ "getattr",
2474
+ "setattr",
2475
+ "lookup",
2476
+ "access",
2477
+ "readlink",
2478
+ "read",
2479
+ "write",
2480
+ "create",
2481
+ "mkdir",
2482
+ "symlink",
2483
+ "mknod",
2484
+ "remove",
2485
+ "rmdir",
2486
+ "rename",
2487
+ "link",
2488
+ "readdir",
2489
+ "readdirplus",
2490
+ "fsstat",
2491
+ "fsinfo",
2492
+ "pathconf",
2493
+ "commit",
2494
+ NULL
2495
+ };
2496
+
2497
+ int sigar_nfs_client_v3_get(sigar_t *sigar,
2498
+ sigar_nfs_client_v3_t *nfs)
2499
+ {
2500
+ return sigar_nfs_get(sigar, "rfsreqcnt_v3", nfs_v3_names, (char *)nfs);
2501
+ }
2502
+
2503
+ int sigar_nfs_server_v3_get(sigar_t *sigar,
2504
+ sigar_nfs_server_v3_t *nfs)
2505
+ {
2506
+ return sigar_nfs_get(sigar, "rfsproccnt_v3", nfs_v3_names, (char *)nfs);
2507
+ }
2508
+
2509
+ int sigar_arp_list_get(sigar_t *sigar,
2510
+ sigar_arp_list_t *arplist)
2511
+ {
2512
+ char *data;
2513
+ int len, rc;
2514
+ struct opthdr *op;
2515
+ size_t nread=0, size=0;
2516
+ const char *size_from;
2517
+
2518
+ sigar_arp_list_create(arplist);
2519
+
2520
+ while ((rc = get_mib2(&sigar->mib2, &op, &data, &len)) == GET_MIB2_OK) {
2521
+ mib2_ipNetToMediaEntry_t *entry;
2522
+ char *end;
2523
+
2524
+ if (op->level != MIB2_IP) {
2525
+ continue;
2526
+ }
2527
+
2528
+ if (op->name == 0) {
2529
+ /* we want to use this size for bincompat */
2530
+ size = ((mib2_ip_t *)data)->ipNetToMediaEntrySize;
2531
+ continue;
2532
+ }
2533
+ else if (op->name != MIB2_IP_MEDIA) {
2534
+ continue;
2535
+ }
2536
+
2537
+ if (size == 0) {
2538
+ size_from = "sizeof";
2539
+ size = sizeof(*entry);
2540
+ }
2541
+ else {
2542
+ size_from = "mib2_ip";
2543
+ }
2544
+
2545
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
2546
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2547
+ "[arp_list] ipNetToMediaEntrySize=%d (from %s)",
2548
+ size, size_from);
2549
+ }
2550
+
2551
+ for (entry = (mib2_ipNetToMediaEntry_t *)data, end = data + len;
2552
+ (char *)entry < end;
2553
+ nread+=size, entry = (mib2_ipNetToMediaEntry_t *)((char *)data+nread))
2554
+ {
2555
+ sigar_arp_t *arp;
2556
+
2557
+ SIGAR_ARP_LIST_GROW(arplist);
2558
+ arp = &arplist->data[arplist->number++];
2559
+
2560
+ sigar_net_address_set(arp->address,
2561
+ entry->ipNetToMediaNetAddress);
2562
+
2563
+ sigar_net_address_mac_set(arp->hwaddr,
2564
+ entry->ipNetToMediaPhysAddress.o_bytes,
2565
+ entry->ipNetToMediaPhysAddress.o_length);
2566
+
2567
+ SIGAR_SSTRCPY(arp->ifname, entry->ipNetToMediaIfIndex.o_bytes);
2568
+
2569
+ arp->flags = entry->ipNetToMediaInfo.ntm_flags;
2570
+ SIGAR_SSTRCPY(arp->type, "ether"); /*XXX*/
2571
+ }
2572
+ }
2573
+
2574
+ if (rc != GET_MIB2_EOD) {
2575
+ close_mib2(&sigar->mib2);
2576
+ return SIGAR_EMIB2;
2577
+ }
2578
+
2579
+ return SIGAR_OK;
2580
+ }
2581
+
2582
+ static int find_port(sigar_t *sigar, struct ps_prochandle *phandle,
2583
+ sigar_pid_t pid, unsigned long port)
2584
+ {
2585
+ DIR *dirp;
2586
+ struct dirent *ent;
2587
+ char pname[PATH_MAX];
2588
+ struct stat64 statb;
2589
+ int found=0;
2590
+
2591
+ sprintf(pname, "/proc/%d/fd", (int)pid);
2592
+
2593
+ if (!(dirp = opendir(pname))) {
2594
+ return 0;
2595
+ }
2596
+
2597
+ while ((ent = readdir(dirp))) {
2598
+ int fd;
2599
+
2600
+ if (!sigar_isdigit(ent->d_name[0])) {
2601
+ continue;
2602
+ }
2603
+ fd = atoi(ent->d_name);
2604
+
2605
+ if (sigar->pfstat64(phandle, fd, &statb) == -1) {
2606
+ continue;
2607
+ }
2608
+
2609
+ if ((statb.st_mode & S_IFMT) == S_IFSOCK) {
2610
+ struct sockaddr_in sin;
2611
+ struct sockaddr *sa = (struct sockaddr *)&sin;
2612
+ socklen_t len = sizeof(sin);
2613
+ int opt, optsz, rc;
2614
+
2615
+ optsz = sizeof(opt);
2616
+ rc = sigar->pgetsockopt(phandle, fd, SOL_SOCKET, SO_TYPE, &opt, &optsz);
2617
+ if (rc != 0) {
2618
+ continue;
2619
+ }
2620
+ if (opt != SOCK_STREAM) {
2621
+ continue;
2622
+ }
2623
+ optsz = sizeof(opt);
2624
+ rc = sigar->pgetsockopt(phandle, fd, SOL_SOCKET, SO_ACCEPTCONN, &opt, &optsz);
2625
+ if (rc != 0) {
2626
+ continue;
2627
+ }
2628
+ if (opt != SO_ACCEPTCONN) {
2629
+ continue;
2630
+ }
2631
+
2632
+ rc = sigar->pgetsockname(phandle, fd, sa, &len);
2633
+ if (rc != 0) {
2634
+ continue;
2635
+ }
2636
+
2637
+ if ((sa->sa_family == AF_INET) ||
2638
+ (sa->sa_family == AF_INET6))
2639
+ {
2640
+ if (ntohs(sin.sin_port) == port) {
2641
+ found = 1;
2642
+ break;
2643
+ }
2644
+ }
2645
+ }
2646
+ }
2647
+
2648
+ closedir(dirp);
2649
+
2650
+ return found;
2651
+ }
2652
+
2653
+ /* derived from /usr/bin/pfiles.c */
2654
+ int sigar_proc_port_get(sigar_t *sigar, int protocol,
2655
+ unsigned long port, sigar_pid_t *pid)
2656
+ {
2657
+ sigar_proc_list_t pids;
2658
+ int i, status, found=0;
2659
+
2660
+ if (sigar->solaris_version < 10) {
2661
+ return SIGAR_ENOTIMPL;
2662
+ }
2663
+
2664
+ if ((status = sigar_init_libproc(sigar)) != SIGAR_OK) {
2665
+ return SIGAR_ENOTIMPL;
2666
+ }
2667
+ status = sigar_proc_list_get(sigar, &pids);
2668
+ if (status != SIGAR_OK) {
2669
+ return status;
2670
+ }
2671
+
2672
+ for (i=0; i<pids.number; i++) {
2673
+ sigar_pid_t ps_id = pids.data[i];
2674
+ struct ps_prochandle *phandle;
2675
+
2676
+ if (ps_id == sigar_pid_get(sigar)) {
2677
+ continue; /* XXX */
2678
+ }
2679
+ status = sigar_pgrab(sigar, ps_id, SIGAR_FUNC, &phandle);
2680
+
2681
+ if (status != SIGAR_OK) {
2682
+ continue;
2683
+ }
2684
+
2685
+ if (sigar->pcreate_agent(phandle) == 0) {
2686
+ found = find_port(sigar, phandle, ps_id, port);
2687
+ sigar->pdestroy_agent(phandle);
2688
+ }
2689
+
2690
+ sigar->pfree(phandle);
2691
+ if (found) {
2692
+ *pid = ps_id;
2693
+ break;
2694
+ }
2695
+ }
2696
+
2697
+ sigar_proc_list_destroy(sigar, &pids);
2698
+
2699
+ return found ? SIGAR_OK : ENOENT;
2700
+ }
2701
+
2702
+ int sigar_os_sys_info_get(sigar_t *sigar,
2703
+ sigar_sys_info_t *sys_info)
2704
+ {
2705
+ char *vendor_version;
2706
+
2707
+ sysinfo(SI_ARCHITECTURE, sys_info->arch, sizeof(sys_info->arch));
2708
+
2709
+ SIGAR_SSTRCPY(sys_info->name, "Solaris");
2710
+ SIGAR_SSTRCPY(sys_info->vendor, "Sun Microsystems");
2711
+
2712
+ if (strEQ(sys_info->version, "5.6")) {
2713
+ vendor_version = "2.6";
2714
+ }
2715
+ else {
2716
+ if ((vendor_version = strchr(sys_info->version, '.'))) {
2717
+ ++vendor_version;
2718
+ }
2719
+ else {
2720
+ vendor_version = sys_info->version;
2721
+ }
2722
+ }
2723
+
2724
+ SIGAR_SSTRCPY(sys_info->vendor_version, vendor_version);
2725
+
2726
+ snprintf(sys_info->description,
2727
+ sizeof(sys_info->description),
2728
+ "%s %s",
2729
+ sys_info->name, sys_info->vendor_version);
2730
+
2731
+ return SIGAR_OK;
2732
+ }