sigar 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/README +2 -0
  2. data/Rakefile +105 -0
  3. data/bindings/SigarBuild.pm +310 -0
  4. data/bindings/SigarWrapper.pm +2978 -0
  5. data/bindings/ruby/examples/arp.rb +24 -0
  6. data/bindings/ruby/examples/cpu_info.rb +35 -0
  7. data/bindings/ruby/examples/df.rb +49 -0
  8. data/bindings/ruby/examples/free.rb +36 -0
  9. data/bindings/ruby/examples/ifconfig.rb +101 -0
  10. data/bindings/ruby/examples/logging.rb +58 -0
  11. data/bindings/ruby/examples/net_info.rb +31 -0
  12. data/bindings/ruby/examples/netstat.rb +71 -0
  13. data/bindings/ruby/examples/pargs.rb +35 -0
  14. data/bindings/ruby/examples/penv.rb +31 -0
  15. data/bindings/ruby/examples/route.rb +48 -0
  16. data/bindings/ruby/examples/version.rb +40 -0
  17. data/bindings/ruby/examples/who.rb +30 -0
  18. data/bindings/ruby/extconf.rb +128 -0
  19. data/bindings/ruby/rbsigar.c +888 -0
  20. data/bindings/ruby/test/cpu_test.rb +40 -0
  21. data/bindings/ruby/test/file_system_test.rb +43 -0
  22. data/bindings/ruby/test/helper.rb +57 -0
  23. data/bindings/ruby/test/loadavg_test.rb +30 -0
  24. data/bindings/ruby/test/mem_test.rb +45 -0
  25. data/bindings/ruby/test/swap_test.rb +36 -0
  26. data/bindings/ruby/test/uptime_test.rb +26 -0
  27. data/include/sigar.h +939 -0
  28. data/include/sigar_fileinfo.h +157 -0
  29. data/include/sigar_format.h +65 -0
  30. data/include/sigar_getline.h +18 -0
  31. data/include/sigar_log.h +80 -0
  32. data/include/sigar_private.h +422 -0
  33. data/include/sigar_ptql.h +53 -0
  34. data/include/sigar_util.h +191 -0
  35. data/src/os/aix/aix_sigar.c +2151 -0
  36. data/src/os/aix/sigar_os.h +73 -0
  37. data/src/os/darwin/Info.plist.in +27 -0
  38. data/src/os/darwin/darwin_sigar.c +3709 -0
  39. data/src/os/darwin/sigar_os.h +80 -0
  40. data/src/os/hpux/hpux_sigar.c +1342 -0
  41. data/src/os/hpux/sigar_os.h +49 -0
  42. data/src/os/linux/linux_sigar.c +2782 -0
  43. data/src/os/linux/sigar_os.h +82 -0
  44. data/src/os/solaris/get_mib2.c +321 -0
  45. data/src/os/solaris/get_mib2.h +127 -0
  46. data/src/os/solaris/kstats.c +181 -0
  47. data/src/os/solaris/procfs.c +97 -0
  48. data/src/os/solaris/sigar_os.h +224 -0
  49. data/src/os/solaris/solaris_sigar.c +2717 -0
  50. data/src/os/win32/peb.c +212 -0
  51. data/src/os/win32/sigar.rc.in +40 -0
  52. data/src/os/win32/sigar_os.h +653 -0
  53. data/src/os/win32/sigar_pdh.h +47 -0
  54. data/src/os/win32/win32_sigar.c +3911 -0
  55. data/src/sigar.c +2428 -0
  56. data/src/sigar_cache.c +179 -0
  57. data/src/sigar_fileinfo.c +815 -0
  58. data/src/sigar_format.c +696 -0
  59. data/src/sigar_getline.c +1849 -0
  60. data/src/sigar_ptql.c +1967 -0
  61. data/src/sigar_signal.c +216 -0
  62. data/src/sigar_util.c +1060 -0
  63. data/src/sigar_version.c.in +22 -0
  64. data/src/sigar_version_autoconf.c.in +22 -0
  65. data/version.properties +11 -0
  66. metadata +131 -0
@@ -0,0 +1,2717 @@
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_cred_get(sigar_t *sigar, sigar_pid_t pid,
723
+ sigar_proc_cred_t *proccred)
724
+ {
725
+ int status = sigar_proc_psinfo_get(sigar, pid);
726
+ psinfo_t *pinfo = sigar->pinfo;
727
+
728
+ if (status != SIGAR_OK) {
729
+ return status;
730
+ }
731
+
732
+ proccred->uid = pinfo->pr_uid;
733
+ proccred->gid = pinfo->pr_gid;
734
+ proccred->euid = pinfo->pr_euid;
735
+ proccred->egid = pinfo->pr_egid;
736
+
737
+ return SIGAR_OK;
738
+ }
739
+
740
+ #define TIMESTRUCT_2MSEC(t) \
741
+ ((t.tv_sec * MILLISEC) + (t.tv_nsec / (NANOSEC/MILLISEC)))
742
+
743
+ int sigar_proc_time_get(sigar_t *sigar, sigar_pid_t pid,
744
+ sigar_proc_time_t *proctime)
745
+ {
746
+ prusage_t usage;
747
+ int status;
748
+
749
+ if ((status = sigar_proc_usage_get(sigar, &usage, pid)) != SIGAR_OK) {
750
+ return status;
751
+ }
752
+
753
+ proctime->start_time = usage.pr_create.tv_sec + sigar->boot_time;
754
+ proctime->start_time *= MILLISEC;
755
+
756
+ if (usage.pr_utime.tv_sec < 0) {
757
+ /* XXX wtf? seen on solaris 10, only for the self process */
758
+ pstatus_t pstatus;
759
+
760
+ status = sigar_proc_status_get(sigar, &pstatus, pid);
761
+ if (status != SIGAR_OK) {
762
+ return status;
763
+ }
764
+
765
+ usage.pr_utime.tv_sec = pstatus.pr_utime.tv_sec;
766
+ usage.pr_utime.tv_nsec = pstatus.pr_utime.tv_nsec;
767
+ usage.pr_stime.tv_sec = pstatus.pr_stime.tv_sec;
768
+ usage.pr_stime.tv_nsec = pstatus.pr_stime.tv_nsec;
769
+ }
770
+
771
+ proctime->user = TIMESTRUCT_2MSEC(usage.pr_utime);
772
+ proctime->sys = TIMESTRUCT_2MSEC(usage.pr_stime);
773
+ proctime->total = proctime->user + proctime->sys;
774
+
775
+ return SIGAR_OK;
776
+ }
777
+
778
+ int sigar_proc_state_get(sigar_t *sigar, sigar_pid_t pid,
779
+ sigar_proc_state_t *procstate)
780
+ {
781
+ int status = sigar_proc_psinfo_get(sigar, pid);
782
+ psinfo_t *pinfo = sigar->pinfo;
783
+
784
+ if (status != SIGAR_OK) {
785
+ return status;
786
+ }
787
+
788
+ SIGAR_SSTRCPY(procstate->name, pinfo->pr_fname);
789
+ procstate->ppid = pinfo->pr_ppid;
790
+ procstate->tty = pinfo->pr_ttydev;
791
+ procstate->priority = pinfo->pr_lwp.pr_pri;
792
+ procstate->nice = pinfo->pr_lwp.pr_nice - NZERO;
793
+ procstate->threads = pinfo->pr_nlwp;
794
+ procstate->processor = pinfo->pr_lwp.pr_onpro;
795
+
796
+ switch (pinfo->pr_lwp.pr_state) {
797
+ case SONPROC:
798
+ case SRUN:
799
+ procstate->state = 'R';
800
+ break;
801
+ case SZOMB:
802
+ procstate->state = 'Z';
803
+ break;
804
+ case SSLEEP:
805
+ procstate->state = 'S';
806
+ break;
807
+ case SSTOP:
808
+ procstate->state = 'T';
809
+ break;
810
+ case SIDL:
811
+ procstate->state = 'D';
812
+ break;
813
+ }
814
+
815
+ return SIGAR_OK;
816
+ }
817
+
818
+ typedef struct {
819
+ int timestamp;
820
+ char *args;
821
+ } pargs_t;
822
+
823
+ static void pargs_free(void *value)
824
+ {
825
+ pargs_t *pargs = (pargs_t *)value;
826
+ if (pargs->args != NULL) {
827
+ free(pargs->args);
828
+ }
829
+ free(pargs);
830
+ }
831
+
832
+ static int ucb_ps_args_get(sigar_t *sigar, sigar_pid_t pid,
833
+ sigar_proc_args_t *procargs,
834
+ int timestamp)
835
+ {
836
+ char buffer[9086], *args=NULL, *arg;
837
+ sigar_cache_entry_t *ent;
838
+ FILE *fp;
839
+ pargs_t *pargs;
840
+
841
+ if (!sigar->pargs) {
842
+ sigar->pargs = sigar_cache_new(15);
843
+ sigar->pargs->free_value = pargs_free;
844
+ }
845
+
846
+ ent = sigar_cache_get(sigar->pargs, pid);
847
+ if (ent->value) {
848
+ pargs = (pargs_t *)ent->value;
849
+ if (pargs->timestamp != timestamp) {
850
+ if (pargs->args) {
851
+ free(pargs->args);
852
+ pargs->args = NULL;
853
+ }
854
+ }
855
+ }
856
+ else {
857
+ pargs = malloc(sizeof(*pargs));
858
+ pargs->args = NULL;
859
+ ent->value = pargs;
860
+ }
861
+
862
+ pargs->timestamp = timestamp;
863
+
864
+ if (pargs->args) {
865
+ args = pargs->args;
866
+ }
867
+ else {
868
+ snprintf(buffer, sizeof(buffer),
869
+ SIGAR_USR_UCB_PS " -ww %ld", (long)pid);
870
+
871
+ if (!(fp = popen(buffer, "r"))) {
872
+ return errno;
873
+ }
874
+ /* skip header */
875
+ (void)fgets(buffer, sizeof(buffer), fp);
876
+ if ((args = fgets(buffer, sizeof(buffer), fp))) {
877
+ int len;
878
+
879
+ /* skip PID,TT,S,TIME */
880
+ args = sigar_skip_multiple_token(args, 4);
881
+ SIGAR_SKIP_SPACE(args);
882
+ len = strlen(args);
883
+ if (len > 0) {
884
+ args[len-1] = '\0'; /* chop \n */
885
+ }
886
+
887
+ pargs->args = malloc(len+1);
888
+ memcpy(pargs->args, args, len);
889
+ }
890
+
891
+ pclose(fp);
892
+
893
+ if (!args) {
894
+ return ESRCH;
895
+ }
896
+ }
897
+
898
+ while (*args && (arg = sigar_getword(&args, ' '))) {
899
+ SIGAR_PROC_ARGS_GROW(procargs);
900
+ procargs->data[procargs->number++] = arg;
901
+ }
902
+
903
+ return SIGAR_OK;
904
+ }
905
+
906
+ int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid,
907
+ sigar_proc_args_t *procargs)
908
+ {
909
+ psinfo_t *pinfo;
910
+ int fd, status;
911
+ char buffer[9086];
912
+ char *argvb[56];
913
+ char **argvp = argvb;
914
+
915
+ int n;
916
+ size_t nread = 0;
917
+ unsigned int argv_size;
918
+
919
+ if ((status = sigar_proc_psinfo_get(sigar, pid)) != SIGAR_OK) {
920
+ return status;
921
+ }
922
+ pinfo = sigar->pinfo;
923
+
924
+ if (pinfo->pr_argc == 0) {
925
+ procargs->number = 0;
926
+ return SIGAR_OK;
927
+ }
928
+ else if (pinfo->pr_dmodel != PR_MODEL_NATIVE) {
929
+ /* we are compiled in 32bit mode
930
+ * punt any 64bit native process,
931
+ * sizeof our structures can't handle.
932
+ */
933
+ if (sigar->use_ucb_ps) {
934
+ return ucb_ps_args_get(sigar, pid, procargs,
935
+ pinfo->pr_start.tv_sec);
936
+ }
937
+ else {
938
+ return ENOTSUP;
939
+ }
940
+ }
941
+
942
+ argv_size = sizeof(*argvp) * pinfo->pr_argc;
943
+
944
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/as");
945
+
946
+ if ((fd = open(buffer, O_RDONLY)) < 0) {
947
+ if ((errno == EACCES) && sigar->use_ucb_ps) {
948
+ return ucb_ps_args_get(sigar, pid, procargs,
949
+ pinfo->pr_start.tv_sec);
950
+ }
951
+ else {
952
+ return PROC_ERRNO;
953
+ }
954
+ }
955
+
956
+ if (argv_size > sizeof(argvb)) {
957
+ argvp = malloc(argv_size);
958
+ }
959
+
960
+ if ((nread = pread(fd, argvp, argv_size, pinfo->pr_argv)) <= 0) {
961
+ close(fd);
962
+ if (argvp != argvb) {
963
+ free(argvp);
964
+ }
965
+ return errno;
966
+ }
967
+
968
+ for (n = 0; n < pinfo->pr_argc; n++) {
969
+ int alen;
970
+ char *arg;
971
+
972
+ if ((nread = pread(fd, buffer, sizeof(buffer)-1, (off_t)argvp[n])) <= 0) {
973
+ close(fd);
974
+ if (argvp != argvb) {
975
+ free(argvp);
976
+ }
977
+ return errno;
978
+ }
979
+
980
+ buffer[nread] = '\0';
981
+ alen = strlen(buffer)+1;
982
+ arg = malloc(alen);
983
+ memcpy(arg, buffer, alen);
984
+
985
+ SIGAR_PROC_ARGS_GROW(procargs);
986
+ procargs->data[procargs->number++] = arg;
987
+ }
988
+
989
+ if (argvp != argvb) {
990
+ free(argvp);
991
+ }
992
+
993
+ close(fd);
994
+
995
+ return SIGAR_OK;
996
+ }
997
+
998
+ int sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid,
999
+ sigar_proc_env_t *procenv)
1000
+ {
1001
+ psinfo_t *pinfo;
1002
+ int fd, status;
1003
+ char buffer[BUFSIZ], *offsets[512];
1004
+ size_t nread;
1005
+ int n=0, max=sizeof(offsets)/sizeof(char *);
1006
+
1007
+ if ((status = sigar_proc_psinfo_get(sigar, pid)) != SIGAR_OK) {
1008
+ return status;
1009
+ }
1010
+ pinfo = sigar->pinfo;
1011
+
1012
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/as");
1013
+
1014
+ if ((fd = open(buffer, O_RDONLY)) < 0) {
1015
+ return PROC_ERRNO;
1016
+ }
1017
+
1018
+ if ((nread = pread(fd, offsets, sizeof(offsets),
1019
+ pinfo->pr_envp)) <= 0)
1020
+ {
1021
+ close(fd);
1022
+ return errno;
1023
+ }
1024
+
1025
+ while ((n < max) && offsets[n]) {
1026
+ char *val;
1027
+ int klen, vlen, status;
1028
+ char key[128]; /* XXX is there a max key size? */
1029
+
1030
+ if ((nread = pread(fd, buffer, sizeof(buffer),
1031
+ (off_t)offsets[n++])) <= 0)
1032
+ {
1033
+ close(fd);
1034
+ return errno;
1035
+ }
1036
+
1037
+ val = strchr(buffer, '=');
1038
+
1039
+ if (val == NULL) {
1040
+ break; /*XXX*/
1041
+ }
1042
+
1043
+ klen = val - buffer;
1044
+ SIGAR_SSTRCPY(key, buffer);
1045
+ key[klen] = '\0';
1046
+ ++val;
1047
+
1048
+ vlen = strlen(val);
1049
+
1050
+ status = procenv->env_getter(procenv->data,
1051
+ key, klen, val, vlen);
1052
+
1053
+ if (status != SIGAR_OK) {
1054
+ /* not an error; just stop iterating */
1055
+ break;
1056
+ }
1057
+ }
1058
+
1059
+ close(fd);
1060
+
1061
+ return SIGAR_OK;
1062
+ }
1063
+
1064
+ int sigar_proc_fd_get(sigar_t *sigar, sigar_pid_t pid,
1065
+ sigar_proc_fd_t *procfd)
1066
+ {
1067
+ int status =
1068
+ sigar_proc_fd_count(sigar, pid, &procfd->total);
1069
+
1070
+ return status;
1071
+ }
1072
+
1073
+ static int sigar_proc_path_exe_get(sigar_t *sigar, sigar_pid_t pid,
1074
+ sigar_proc_exe_t *procexe)
1075
+ {
1076
+ /* solaris 10+ */
1077
+ char buffer[BUFSIZ];
1078
+
1079
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/path/a.out");
1080
+ if (!proc_readlink(buffer, procexe->name, sizeof(procexe->name))) {
1081
+ procexe->name[0] = '\0';
1082
+ }
1083
+
1084
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/path/cwd");
1085
+ if (!proc_readlink(buffer, procexe->cwd, sizeof(procexe->cwd))) {
1086
+ procexe->cwd[0] = '\0';
1087
+ }
1088
+
1089
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/path/root");
1090
+ if (!proc_readlink(buffer, procexe->root, sizeof(procexe->root))) {
1091
+ procexe->root[0] = '\0';
1092
+ }
1093
+
1094
+ return SIGAR_OK;
1095
+ }
1096
+
1097
+ static int proc_module_get_exe(void *data, char *name, int len)
1098
+ {
1099
+ sigar_proc_exe_t *procexe = (sigar_proc_exe_t *)data;
1100
+ SIGAR_STRNCPY(procexe->name, name, sizeof(procexe->name));
1101
+ return !SIGAR_OK; /* break loop */
1102
+ }
1103
+
1104
+ static int sigar_which_exe_get(sigar_t *sigar, sigar_proc_exe_t *procexe)
1105
+ {
1106
+ char *path = getenv("PATH");
1107
+ char exe[PATH_MAX];
1108
+ if (path == NULL) {
1109
+ return EINVAL;
1110
+ }
1111
+
1112
+ while (path) {
1113
+ char *ptr = strchr(path, ':');
1114
+ if (!ptr) {
1115
+ break;
1116
+ }
1117
+ exe[0] = '\0';
1118
+ strncat(exe, path, ptr-path);
1119
+ strncat(exe, "/", 1);
1120
+ strcat(exe, procexe->name);
1121
+ if (access(exe, X_OK) == 0) {
1122
+ SIGAR_STRNCPY(procexe->name, exe, sizeof(procexe->name));
1123
+ break;
1124
+ }
1125
+ path = ptr+1;
1126
+ }
1127
+
1128
+ return ENOENT;
1129
+ }
1130
+
1131
+ int sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid,
1132
+ sigar_proc_exe_t *procexe)
1133
+ {
1134
+ int status;
1135
+ char buffer[BUFSIZ];
1136
+ struct ps_prochandle *phandle;
1137
+
1138
+ if (sigar->solaris_version >= 10) {
1139
+ return sigar_proc_path_exe_get(sigar, pid, procexe);
1140
+ }
1141
+
1142
+ if ((status = sigar_init_libproc(sigar)) != SIGAR_OK) {
1143
+ return status;
1144
+ }
1145
+
1146
+ procexe->name[0] = '\0';
1147
+
1148
+ /* Pgrab would return G_SELF error */
1149
+ if (pid == sigar_pid_get(sigar)) {
1150
+ sigar_proc_modules_t procmods;
1151
+ procmods.module_getter = proc_module_get_exe;
1152
+ procmods.data = procexe;
1153
+
1154
+ status =
1155
+ sigar_dlinfo_modules(sigar, &procmods);
1156
+ if (status == SIGAR_OK) {
1157
+ if (procexe->name[0] != '/') {
1158
+ sigar_which_exe_get(sigar, procexe);
1159
+ }
1160
+ }
1161
+ }
1162
+ else {
1163
+ status = sigar_pgrab(sigar, pid, SIGAR_FUNC, &phandle);
1164
+
1165
+ if (status == SIGAR_OK) {
1166
+ sigar->pexename(phandle, procexe->name, sizeof(procexe->name));
1167
+ sigar->pfree(phandle);
1168
+ }
1169
+ }
1170
+
1171
+ if (procexe->name[0] == '\0') {
1172
+ /*XXX*/
1173
+ }
1174
+
1175
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/cwd");
1176
+
1177
+ if (!sigar->pdirname(buffer, procexe->cwd, sizeof(procexe->cwd))) {
1178
+ procexe->cwd[0] = '\0';
1179
+ }
1180
+
1181
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/root");
1182
+
1183
+ if (!(sigar->pdirname(buffer, procexe->root, sizeof(procexe->root)))) {
1184
+ procexe->root[0] = '\0';
1185
+ }
1186
+
1187
+ return SIGAR_OK;
1188
+ }
1189
+
1190
+ static int sigar_read_xmaps(sigar_t *sigar,
1191
+ prxmap_t *xmaps, int total,
1192
+ unsigned long *last_inode,
1193
+ struct ps_prochandle *phandle,
1194
+ sigar_proc_modules_t *procmods)
1195
+ {
1196
+ int status, i;
1197
+ unsigned long inode;
1198
+ char buffer[BUFSIZ];
1199
+
1200
+ for (i=0; i<total; i++) {
1201
+ if (xmaps[i].pr_mflags & MA_ANON) {
1202
+ continue; /* heap, stack, etc */
1203
+ }
1204
+
1205
+ inode = xmaps[i].pr_ino;
1206
+
1207
+ if ((inode == 0) || (inode == *last_inode)) {
1208
+ *last_inode = 0;
1209
+ continue;
1210
+ }
1211
+
1212
+ *last_inode = inode;
1213
+
1214
+ sigar->pobjname(phandle, xmaps[i].pr_vaddr, buffer, sizeof(buffer));
1215
+
1216
+ status =
1217
+ procmods->module_getter(procmods->data, buffer, strlen(buffer));
1218
+
1219
+ if (status != SIGAR_OK) {
1220
+ /* not an error; just stop iterating */
1221
+ return status;
1222
+ }
1223
+ }
1224
+
1225
+ return SIGAR_OK;
1226
+ }
1227
+
1228
+ static int sigar_pgrab_modules(sigar_t *sigar, sigar_pid_t pid,
1229
+ sigar_proc_modules_t *procmods)
1230
+ {
1231
+ int fd, pstatus;
1232
+ off_t map_size, nread;
1233
+ unsigned long last_inode = 0;
1234
+ prxmap_t xmaps[15]; /* ~2K */
1235
+ struct ps_prochandle *phandle;
1236
+ struct stat statbuf;
1237
+ char buffer[BUFSIZ];
1238
+
1239
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/xmap");
1240
+
1241
+ if ((fd = open(buffer, O_RDONLY)) < 0) {
1242
+ return errno;
1243
+ }
1244
+
1245
+ if (fstat(fd, &statbuf) < 0) {
1246
+ close(fd);
1247
+ return errno;
1248
+ }
1249
+
1250
+ map_size = statbuf.st_size;
1251
+
1252
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
1253
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
1254
+ "[%s] pid=%d, size=%d",
1255
+ SIGAR_FUNC, pid, map_size);
1256
+ }
1257
+
1258
+ if ((pstatus = sigar_init_libproc(sigar)) != SIGAR_OK) {
1259
+ close(fd);
1260
+ return pstatus;
1261
+ }
1262
+
1263
+ pstatus = sigar_pgrab(sigar, pid, SIGAR_FUNC, &phandle);
1264
+
1265
+ if (pstatus != SIGAR_OK) {
1266
+ close(fd);
1267
+ return pstatus;
1268
+ }
1269
+
1270
+ for (nread=0; nread<statbuf.st_size; ) {
1271
+ off_t wanted = map_size > sizeof(xmaps) ? sizeof(xmaps) : map_size;
1272
+ int total = wanted / sizeof(prxmap_t);
1273
+
1274
+ if (pread(fd, xmaps, wanted, nread) != wanted) {
1275
+ close(fd);
1276
+ sigar->pfree(phandle);
1277
+ return errno;
1278
+ }
1279
+
1280
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
1281
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
1282
+ "[%s] nread=%d, map_size=%d, wanted=%d, total=%d",
1283
+ SIGAR_FUNC,
1284
+ nread, map_size, wanted, total);
1285
+ }
1286
+
1287
+ if (sigar_read_xmaps(sigar, xmaps, total,
1288
+ &last_inode,
1289
+ phandle, procmods) != SIGAR_OK)
1290
+ {
1291
+ break;
1292
+ }
1293
+
1294
+ nread += wanted;
1295
+ map_size -= wanted;
1296
+ }
1297
+
1298
+ close(fd);
1299
+
1300
+ sigar->pfree(phandle);
1301
+
1302
+ return SIGAR_OK;
1303
+ }
1304
+
1305
+ int sigar_proc_modules_get(sigar_t *sigar, sigar_pid_t pid,
1306
+ sigar_proc_modules_t *procmods)
1307
+ {
1308
+ if (pid == sigar_pid_get(sigar)) {
1309
+ /* Pgrab would return G_SELF, this is faster anyhow */
1310
+ /* XXX one difference to Pgrab, first entry is not the exe name */
1311
+ return sigar_dlinfo_modules(sigar, procmods);
1312
+ }
1313
+ else {
1314
+ return sigar_pgrab_modules(sigar, pid, procmods);
1315
+ }
1316
+ }
1317
+
1318
+ #define TIME_NSEC(t) \
1319
+ (SIGAR_SEC2NANO((t).tv_sec) + (sigar_uint64_t)(t).tv_nsec)
1320
+
1321
+ int sigar_thread_cpu_get(sigar_t *sigar,
1322
+ sigar_uint64_t id,
1323
+ sigar_thread_cpu_t *cpu)
1324
+ {
1325
+ struct lwpinfo info;
1326
+
1327
+ if (id != 0) {
1328
+ return SIGAR_ENOTIMPL;
1329
+ }
1330
+
1331
+ _lwp_info(&info);
1332
+
1333
+ cpu->user = TIME_NSEC(info.lwp_utime);
1334
+ cpu->sys = TIME_NSEC(info.lwp_stime);
1335
+ cpu->total = TIME_NSEC(info.lwp_utime) + TIME_NSEC(info.lwp_stime);
1336
+
1337
+ return SIGAR_OK;
1338
+ }
1339
+
1340
+ #include <sys/mnttab.h>
1341
+
1342
+ int sigar_os_fs_type_get(sigar_file_system_t *fsp)
1343
+ {
1344
+ char *type = fsp->sys_type_name;
1345
+
1346
+ switch (*type) {
1347
+ case 'u':
1348
+ if (strEQ(type, "ufs")) {
1349
+ fsp->type = SIGAR_FSTYPE_LOCAL_DISK;
1350
+ }
1351
+ break;
1352
+ /* XXX */
1353
+ }
1354
+
1355
+ return fsp->type;
1356
+ }
1357
+
1358
+ int sigar_file_system_list_get(sigar_t *sigar,
1359
+ sigar_file_system_list_t *fslist)
1360
+ {
1361
+ struct mnttab ent;
1362
+ sigar_file_system_t *fsp;
1363
+ FILE *fp = fopen(MNTTAB, "r");
1364
+
1365
+ if (!fp) {
1366
+ return errno;
1367
+ }
1368
+
1369
+ sigar_file_system_list_create(fslist);
1370
+
1371
+ while (getmntent(fp, &ent) == 0) {
1372
+ if (strstr(ent.mnt_mntopts, "ignore")) {
1373
+ continue; /* e.g. vold */
1374
+ }
1375
+
1376
+ SIGAR_FILE_SYSTEM_LIST_GROW(fslist);
1377
+
1378
+ fsp = &fslist->data[fslist->number++];
1379
+
1380
+ SIGAR_SSTRCPY(fsp->dir_name, ent.mnt_mountp);
1381
+ SIGAR_SSTRCPY(fsp->dev_name, ent.mnt_special);
1382
+ SIGAR_SSTRCPY(fsp->sys_type_name, ent.mnt_fstype);
1383
+ SIGAR_SSTRCPY(fsp->options, ent.mnt_mntopts);
1384
+ sigar_fs_type_init(fsp);
1385
+ }
1386
+
1387
+ fclose(fp);
1388
+
1389
+ return SIGAR_OK;
1390
+ }
1391
+
1392
+ typedef struct {
1393
+ char device[PATH_MAX];
1394
+ char name[8];
1395
+ int instance;
1396
+ } fsdev_path_t;
1397
+
1398
+ typedef struct {
1399
+ char name[256];
1400
+ int is_partition;
1401
+ sigar_disk_usage_t disk;
1402
+ } iodev_t;
1403
+
1404
+ static fsdev_path_t *get_fsdev_paths(sigar_t *sigar,
1405
+ sigar_file_system_list_t *fslist)
1406
+ {
1407
+ int i, ndisk, size;
1408
+ char buffer[BUFSIZ], *ptr;
1409
+ char *dev, *inst, *drv;
1410
+ fsdev_path_t *paths, *mapping;
1411
+ FILE *fp = fopen("/etc/path_to_inst", "r");
1412
+
1413
+ if (!fp) {
1414
+ return NULL;
1415
+ }
1416
+
1417
+ for (i=0, ndisk=0; i<fslist->number; i++) {
1418
+ sigar_file_system_t *fsp = &fslist->data[i];
1419
+ if (fsp->type == SIGAR_FSTYPE_LOCAL_DISK) {
1420
+ ndisk++;
1421
+ }
1422
+ }
1423
+
1424
+ size = sizeof(*paths) * (ndisk+1);
1425
+ mapping = paths = malloc(size);
1426
+ memset(mapping, '\0', size);
1427
+
1428
+ while ((ptr = fgets(buffer, sizeof(buffer), fp))) {
1429
+ /* eat dust java */
1430
+ char *q;
1431
+
1432
+ SIGAR_SKIP_SPACE(ptr);
1433
+ if (*ptr == '#') {
1434
+ continue;
1435
+ }
1436
+ if (*ptr == '"') {
1437
+ ptr++;
1438
+ }
1439
+ dev = ptr;
1440
+ if (!(q = strchr(ptr, '"'))) {
1441
+ continue;
1442
+ }
1443
+ ptr = q+1;
1444
+ *q = '\0';
1445
+ SIGAR_SKIP_SPACE(ptr);
1446
+ inst = ptr;
1447
+ while (sigar_isdigit(*ptr)) {
1448
+ ptr++;
1449
+ }
1450
+ *ptr = '\0';
1451
+ ptr++;
1452
+ SIGAR_SKIP_SPACE(ptr);
1453
+ if (*ptr == '"') {
1454
+ ptr++;
1455
+ }
1456
+ drv = ptr;
1457
+ if (!(q = strchr(ptr, '"'))) {
1458
+ continue;
1459
+ }
1460
+ *q = '\0';
1461
+
1462
+ if (!(strEQ(drv, "sd") ||
1463
+ strEQ(drv, "ssd") ||
1464
+ strEQ(drv, "st") ||
1465
+ strEQ(drv, "dad") ||
1466
+ strEQ(drv, "cmdk")))
1467
+ {
1468
+ continue;
1469
+ }
1470
+
1471
+ paths->instance = atoi(inst);
1472
+ if (!kstat_lookup(sigar->kc, drv, paths->instance, NULL)) {
1473
+ continue;
1474
+ }
1475
+
1476
+ SIGAR_SSTRCPY(paths->device, dev);
1477
+ SIGAR_SSTRCPY(paths->name, drv);
1478
+
1479
+ if (--ndisk < 0) {
1480
+ /* XXX prevent overflow */
1481
+ break;
1482
+ }
1483
+ paths++;
1484
+ }
1485
+ fclose(fp);
1486
+
1487
+ return mapping;
1488
+ }
1489
+
1490
+ static int create_fsdev_cache(sigar_t *sigar)
1491
+ {
1492
+ fsdev_path_t *paths, *mapping;
1493
+ sigar_file_system_list_t fslist;
1494
+ int i, j;
1495
+ int status;
1496
+ int debug = SIGAR_LOG_IS_DEBUG(sigar);
1497
+
1498
+ sigar->fsdev = sigar_cache_new(15);
1499
+
1500
+ status = sigar_file_system_list_get(sigar, &fslist);
1501
+
1502
+ if (status != SIGAR_OK) {
1503
+ return status;
1504
+ }
1505
+
1506
+ if (!(mapping = get_fsdev_paths(sigar, &fslist))) {
1507
+ sigar_file_system_list_destroy(sigar, &fslist);
1508
+ return ENOENT;
1509
+ }
1510
+
1511
+ for (i=0; i<fslist.number; i++) {
1512
+ sigar_file_system_t *fsp = &fslist.data[i];
1513
+
1514
+ if (fsp->type == SIGAR_FSTYPE_LOCAL_DISK) {
1515
+ char device[PATH_MAX+1], *ptr=device;
1516
+ int len = readlink(fsp->dev_name, device, sizeof(device)-1);
1517
+ char *s;
1518
+ char partition;
1519
+
1520
+ if (len < 0) {
1521
+ continue;
1522
+ }
1523
+ device[len] = '\0';
1524
+
1525
+ if (debug) {
1526
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG, "[fsdev] name=%s, dev=%s",
1527
+ fsp->dev_name, device);
1528
+ }
1529
+
1530
+ while (strnEQ(ptr, "../", 3)) {
1531
+ ptr += 3;
1532
+ }
1533
+ if (strnEQ(ptr, "devices", 7)) {
1534
+ ptr += 7;
1535
+ }
1536
+ if ((s = strchr(ptr, ':'))) {
1537
+ partition = *(s+1);
1538
+ }
1539
+ else {
1540
+ continue;
1541
+ }
1542
+
1543
+ for (j=0, paths=mapping; paths->name[0]; j++) {
1544
+ if (strnEQ(paths->device, ptr, strlen(paths->device))) {
1545
+ sigar_cache_entry_t *ent;
1546
+ struct stat sb;
1547
+ int retval = stat(fsp->dir_name, &sb);
1548
+ iodev_t *iodev;
1549
+
1550
+ if (retval == 0) {
1551
+ iodev = malloc(sizeof(*iodev));
1552
+
1553
+ SIGAR_DISK_STATS_INIT(&iodev->disk);
1554
+ /* e.g. sd9,g
1555
+ * module == sd
1556
+ * instance == 9
1557
+ * partition == 8
1558
+ */
1559
+ snprintf(iodev->name, sizeof(iodev->name), "%s%d,%c",
1560
+ paths->name, paths->instance, partition);
1561
+
1562
+ ent = sigar_cache_get(sigar->fsdev, SIGAR_FSDEV_ID(sb));
1563
+ ent->value = iodev;
1564
+
1565
+ if (debug) {
1566
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
1567
+ "[fsdev] map %s -> %s",
1568
+ fsp->dir_name, iodev->name);
1569
+ }
1570
+ }
1571
+ break;
1572
+ }
1573
+ paths++;
1574
+ }
1575
+ }
1576
+ }
1577
+
1578
+ free(mapping);
1579
+ sigar_file_system_list_destroy(sigar, &fslist);
1580
+
1581
+ return SIGAR_OK;
1582
+ }
1583
+
1584
+ static int io_kstat_read(sigar_t *sigar,
1585
+ sigar_disk_usage_t *disk,
1586
+ kstat_t *ksp)
1587
+ {
1588
+ kstat_io_t *io;
1589
+
1590
+ kstat_read(sigar->kc, ksp, NULL);
1591
+
1592
+ io = (kstat_io_t *)ksp->ks_data;
1593
+
1594
+ disk->reads = io->reads;
1595
+ disk->writes = io->writes;
1596
+ disk->read_bytes = io->nread;
1597
+ disk->write_bytes = io->nwritten;
1598
+ disk->qtime = io->wlentime;
1599
+ disk->rtime = io->rlentime;
1600
+ disk->wtime = io->wlentime;
1601
+ disk->time = disk->rtime + disk->wtime;
1602
+ disk->snaptime = ksp->ks_snaptime;
1603
+
1604
+ return SIGAR_OK;
1605
+ }
1606
+
1607
+
1608
+ static int sigar_kstat_disk_usage_get(sigar_t *sigar, const char *name,
1609
+ sigar_disk_usage_t *disk,
1610
+ kstat_t **kio)
1611
+ {
1612
+ kstat_t *ksp;
1613
+
1614
+ if (sigar_kstat_update(sigar) == -1) {
1615
+ return errno;
1616
+ }
1617
+
1618
+ for (ksp = sigar->kc->kc_chain;
1619
+ ksp;
1620
+ ksp = ksp->ks_next)
1621
+ {
1622
+ if (ksp->ks_type != KSTAT_TYPE_IO) {
1623
+ continue;
1624
+ }
1625
+ if (strEQ(ksp->ks_name, name)) {
1626
+ int status = io_kstat_read(sigar, disk, ksp);
1627
+ *kio = ksp;
1628
+ return status;
1629
+ }
1630
+ }
1631
+
1632
+ return ENXIO;
1633
+ }
1634
+
1635
+ static int simple_hash(const char *s)
1636
+ {
1637
+ int hash = 0;
1638
+ while (*s) {
1639
+ hash = 31*hash + *s++;
1640
+ }
1641
+ return hash;
1642
+ }
1643
+
1644
+ int sigar_disk_usage_get(sigar_t *sigar, const char *name,
1645
+ sigar_disk_usage_t *disk)
1646
+ {
1647
+ kstat_t *ksp;
1648
+ int status;
1649
+ iodev_t *iodev = NULL;
1650
+ sigar_cache_entry_t *ent;
1651
+ sigar_uint64_t id;
1652
+
1653
+ SIGAR_DISK_STATS_INIT(disk);
1654
+
1655
+ if (!sigar->fsdev) {
1656
+ if (create_fsdev_cache(sigar) != SIGAR_OK) {
1657
+ return SIGAR_OK;
1658
+ }
1659
+ }
1660
+
1661
+ if (*name == '/') {
1662
+ struct stat sb;
1663
+
1664
+ if (stat(name, &sb) < 0) {
1665
+ return errno;
1666
+ }
1667
+
1668
+ id = SIGAR_FSDEV_ID(sb);
1669
+ ent = sigar_cache_get(sigar->fsdev, id);
1670
+ if (ent->value == NULL) {
1671
+ return ENXIO;
1672
+ }
1673
+ iodev = (iodev_t *)ent->value;
1674
+
1675
+ status = sigar_kstat_disk_usage_get(sigar, iodev->name, disk, &ksp);
1676
+ }
1677
+ else {
1678
+ status = sigar_kstat_disk_usage_get(sigar, name, disk, &ksp);
1679
+ if (status != SIGAR_OK) {
1680
+ return status;
1681
+ }
1682
+ id = simple_hash(name); /*XXX*/
1683
+ ent = sigar_cache_get(sigar->fsdev, id);
1684
+ if (ent->value) {
1685
+ iodev = (iodev_t *)ent->value;
1686
+ }
1687
+ else {
1688
+ ent->value = iodev = malloc(sizeof(*iodev));
1689
+ SIGAR_SSTRCPY(iodev->name, name);
1690
+ SIGAR_DISK_STATS_INIT(&iodev->disk);
1691
+ }
1692
+ }
1693
+
1694
+ /* service_time formula derived from opensolaris.org:iostat.c */
1695
+ if ((status == SIGAR_OK) && iodev) {
1696
+ sigar_uint64_t delta;
1697
+ double avw, avr, tps, mtps;
1698
+ double etime, hr_etime;
1699
+
1700
+ if (iodev->disk.snaptime) {
1701
+ delta = disk->snaptime - iodev->disk.snaptime;
1702
+ }
1703
+ else {
1704
+ delta = ksp->ks_crtime - ksp->ks_snaptime;
1705
+ }
1706
+
1707
+ hr_etime = (double)delta;
1708
+ if (hr_etime == 0.0) {
1709
+ hr_etime = (double)NANOSEC;
1710
+ }
1711
+ etime = hr_etime / (double)NANOSEC;
1712
+
1713
+ tps =
1714
+ (((double)(disk->reads - iodev->disk.reads)) / etime) +
1715
+ (((double)(disk->writes - iodev->disk.writes)) / etime);
1716
+
1717
+ delta = disk->wtime - iodev->disk.wtime;
1718
+ if (delta) {
1719
+ avw = (double)delta;
1720
+ avw /= hr_etime;
1721
+ }
1722
+ else {
1723
+ avw = 0.0;
1724
+ }
1725
+
1726
+ delta = disk->rtime - iodev->disk.rtime;
1727
+ if (delta) {
1728
+ avr = (double)delta;
1729
+ avr /= hr_etime;
1730
+ }
1731
+ else {
1732
+ avr = 0.0;
1733
+ }
1734
+
1735
+ disk->queue = avw;
1736
+ disk->service_time = 0.0;
1737
+
1738
+ if (tps && (avw != 0.0 || avr != 0.0)) {
1739
+ mtps = 1000.0 / tps;
1740
+ if (avw != 0.0) {
1741
+ disk->service_time += avw * mtps;
1742
+ }
1743
+ if (avr != 0.0) {
1744
+ disk->service_time += avr * mtps;
1745
+ }
1746
+ }
1747
+
1748
+ memcpy(&iodev->disk, disk, sizeof(iodev->disk));
1749
+ }
1750
+
1751
+ return status;
1752
+ }
1753
+
1754
+ int sigar_file_system_usage_get(sigar_t *sigar,
1755
+ const char *dirname,
1756
+ sigar_file_system_usage_t *fsusage)
1757
+ {
1758
+ int status = sigar_statvfs(sigar, dirname, fsusage);
1759
+
1760
+ if (status != SIGAR_OK) {
1761
+ return status;
1762
+ }
1763
+
1764
+ fsusage->use_percent = sigar_file_system_usage_calc_used(sigar, fsusage);
1765
+
1766
+ sigar_disk_usage_get(sigar, dirname, &fsusage->disk);
1767
+
1768
+ return SIGAR_OK;
1769
+ }
1770
+
1771
+ int sigar_cpu_info_list_get(sigar_t *sigar,
1772
+ sigar_cpu_info_list_t *cpu_infos)
1773
+ {
1774
+ processor_info_t stats;
1775
+ unsigned int i;
1776
+ int status = SIGAR_OK;
1777
+ int brand = -1;
1778
+ sigar_cache_t *chips;
1779
+ int is_debug = SIGAR_LOG_IS_DEBUG(sigar);
1780
+ int nsockets = 0;
1781
+
1782
+ if (sigar_kstat_update(sigar) == -1) { /* for sigar->ncpu */
1783
+ return errno;
1784
+ }
1785
+
1786
+ /*
1787
+ * stats we care about will be the same for each
1788
+ * online processor, so just grab the first.
1789
+ */
1790
+ for (i=0; i<sigar->ncpu; i++) {
1791
+ processorid_t id = sigar->ks.cpuid[i];
1792
+
1793
+ if ((status = processor_info(id, &stats)) < 0) {
1794
+ continue;
1795
+ }
1796
+ else {
1797
+ status = SIGAR_OK;
1798
+ break;
1799
+ }
1800
+ }
1801
+
1802
+ if (status != SIGAR_OK) {
1803
+ /* should never happen */
1804
+ return ENOENT;
1805
+ }
1806
+
1807
+ sigar_cpu_info_list_create(cpu_infos);
1808
+ chips = sigar_cache_new(16);
1809
+ chips->free_value = free_chip_id;
1810
+
1811
+ for (i=0; i<sigar->ncpu; i++) {
1812
+ sigar_cpu_info_t *info;
1813
+ int chip_id = get_chip_id(sigar, i);
1814
+
1815
+ if (chip_id != -1) {
1816
+ sigar_cache_entry_t *ent =
1817
+ sigar_cache_get(chips, chip_id);
1818
+
1819
+ if (ent->value) {
1820
+ if (!sigar->cpu_list_cores) {
1821
+ continue;
1822
+ }
1823
+ }
1824
+ else {
1825
+ ++nsockets;
1826
+ ent->value = chips; /*anything non-NULL*/
1827
+ if (is_debug) {
1828
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
1829
+ "[cpu_list] Merging info of"
1830
+ " logical processors for chip_id=%d",
1831
+ chip_id);
1832
+ }
1833
+ }
1834
+ }
1835
+ else {
1836
+ ++nsockets;
1837
+ }
1838
+
1839
+ SIGAR_CPU_INFO_LIST_GROW(cpu_infos);
1840
+
1841
+ info = &cpu_infos->data[cpu_infos->number++];
1842
+
1843
+ SIGAR_SSTRCPY(info->model, stats.pi_processor_type);
1844
+
1845
+ if (brand == -1) {
1846
+ brand = get_chip_brand(sigar, i, info);
1847
+ }
1848
+
1849
+ if (strEQ(info->model, "i386")) {
1850
+ if (!brand) {
1851
+ /* assume Intel on x86 */
1852
+ SIGAR_SSTRCPY(info->vendor, "Intel");
1853
+ }
1854
+ SIGAR_SSTRCPY(info->model, "x86");
1855
+ }
1856
+ else {
1857
+ if (!brand) {
1858
+ /* assume Sun */
1859
+ SIGAR_SSTRCPY(info->vendor, "Sun");
1860
+ }
1861
+ /* s/sparc/Sparc/ */
1862
+ info->model[0] = toupper(info->model[0]);
1863
+ }
1864
+
1865
+ if (brand) {
1866
+ SIGAR_SSTRCPY(info->vendor, cpu_infos->data[0].vendor);
1867
+ }
1868
+
1869
+ info->mhz = stats.pi_clock;
1870
+ info->cache_size = SIGAR_FIELD_NOTIMPL; /*XXX*/
1871
+ }
1872
+
1873
+ sigar_cache_destroy(chips);
1874
+
1875
+ for (i=0; i<cpu_infos->number; i++) {
1876
+ sigar_cpu_info_t *info = &cpu_infos->data[i];
1877
+ info->total_sockets = nsockets;
1878
+ info->total_cores = sigar->ncpu;
1879
+ info->cores_per_socket = sigar->ncpu / nsockets;
1880
+ }
1881
+
1882
+ return SIGAR_OK;
1883
+ }
1884
+
1885
+ int sigar_net_route_list_get(sigar_t *sigar,
1886
+ sigar_net_route_list_t *routelist)
1887
+
1888
+ {
1889
+ char *data;
1890
+ int len, rc;
1891
+ struct opthdr *op;
1892
+ size_t nread=0, size=0;
1893
+ const char *size_from;
1894
+
1895
+ sigar_net_route_list_create(routelist);
1896
+
1897
+ while ((rc = get_mib2(&sigar->mib2, &op, &data, &len)) == GET_MIB2_OK) {
1898
+ mib2_ipRouteEntry_t *entry;
1899
+ char *end;
1900
+
1901
+ if (op->level != MIB2_IP) {
1902
+ continue;
1903
+ }
1904
+
1905
+ if (op->name == 0) {
1906
+ /* we want to use this size for bincompat */
1907
+ size = ((mib2_ip_t *)data)->ipRouteEntrySize;
1908
+ continue;
1909
+ }
1910
+ else if (op->name != MIB2_IP_21) {
1911
+ continue;
1912
+ }
1913
+
1914
+ if (size == 0) {
1915
+ size_from = "sizeof";
1916
+ size = sizeof(*entry);
1917
+ }
1918
+ else {
1919
+ size_from = "mib2_ip";
1920
+ }
1921
+
1922
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
1923
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
1924
+ "[route_list] ipRouteEntrySize=%d (from %s)",
1925
+ size, size_from);
1926
+ }
1927
+
1928
+ for (entry = (mib2_ipRouteEntry_t *)data, end = data + len;
1929
+ (char *)entry < end;
1930
+ nread+=size, entry = (mib2_ipRouteEntry_t *)((char *)data+nread))
1931
+ {
1932
+ sigar_net_route_t *route;
1933
+ int type = entry->ipRouteInfo.re_ire_type;
1934
+
1935
+ /* filter same as netstat -r */
1936
+ if ((type == IRE_CACHE) ||
1937
+ (type == IRE_BROADCAST) ||
1938
+ (type == IRE_LOCAL))
1939
+ {
1940
+ continue;
1941
+ }
1942
+
1943
+ SIGAR_NET_ROUTE_LIST_GROW(routelist);
1944
+ route = &routelist->data[routelist->number++];
1945
+
1946
+ sigar_net_address_set(route->destination,
1947
+ entry->ipRouteDest);
1948
+
1949
+ sigar_net_address_set(route->gateway,
1950
+ entry->ipRouteNextHop);
1951
+
1952
+ sigar_net_address_set(route->mask,
1953
+ entry->ipRouteMask);
1954
+
1955
+ route->refcnt = entry->ipRouteInfo.re_ref;
1956
+ route->irtt = entry->ipRouteInfo.re_rtt;
1957
+ route->metric = entry->ipRouteMetric1;
1958
+
1959
+ SIGAR_SSTRCPY(route->ifname, entry->ipRouteIfIndex.o_bytes);
1960
+
1961
+ route->flags = RTF_UP;
1962
+ if ((route->destination.addr.in == 0) &&
1963
+ (route->mask.addr.in == 0))
1964
+ {
1965
+ route->flags |= RTF_GATEWAY;
1966
+ }
1967
+
1968
+ route->use = route->window = route->mtu =
1969
+ SIGAR_FIELD_NOTIMPL; /*XXX*/
1970
+ }
1971
+ }
1972
+
1973
+ if (rc != GET_MIB2_EOD) {
1974
+ close_mib2(&sigar->mib2);
1975
+ return SIGAR_EMIB2;
1976
+ }
1977
+
1978
+ return SIGAR_OK;
1979
+ }
1980
+
1981
+ static void ifstat_kstat_common(sigar_net_interface_stat_t *ifstat,
1982
+ kstat_named_t *data, int ndata)
1983
+ {
1984
+ int i;
1985
+
1986
+ for (i=0; i<ndata; i++) {
1987
+ sigar_uint64_t value = data[i].value.KSTAT_UINT;
1988
+
1989
+ char *ptr = data[i].name;
1990
+
1991
+ switch (*ptr) {
1992
+ case 'c':
1993
+ if (strEQ(ptr, "collisions")) {
1994
+ ifstat->tx_collisions = value;
1995
+ }
1996
+ break;
1997
+ case 'd':
1998
+ if (strEQ(ptr, "drop")) {
1999
+ ifstat->rx_dropped = value;
2000
+ ifstat->tx_dropped = value;
2001
+ }
2002
+ break;
2003
+ case 'i':
2004
+ if (strEQ(ptr, "ipackets")) {
2005
+ if (ifstat->rx_packets == 0) {
2006
+ ifstat->rx_packets = value;
2007
+ }
2008
+ }
2009
+ else if (strEQ(ptr, "ipackets64")) {
2010
+ ifstat->rx_packets = data[i].value.ui64;
2011
+ }
2012
+ else if (strEQ(ptr, "ierrors")) {
2013
+ ifstat->rx_errors = value;
2014
+ }
2015
+ else if (strEQ(ptr, "ifspeed")) {
2016
+ ifstat->speed = value;
2017
+ }
2018
+ break;
2019
+ case 'f':
2020
+ if (strEQ(ptr, "framing")) {
2021
+ ifstat->rx_frame = value;
2022
+ }
2023
+ break;
2024
+ case 'm':
2025
+ if (strEQ(ptr, "missed")) {
2026
+ ifstat->rx_dropped = value;
2027
+ ifstat->tx_dropped = value;
2028
+ }
2029
+ break;
2030
+ case 'n':
2031
+ if (strEQ(ptr, "nocarrier")) {
2032
+ ifstat->tx_carrier = value;
2033
+ }
2034
+ break;
2035
+ case 'o':
2036
+ if (strEQ(ptr, "obytes")) {
2037
+ if (ifstat->tx_bytes == 0) {
2038
+ ifstat->tx_bytes = value;
2039
+ }
2040
+ }
2041
+ else if (strEQ(ptr, "obytes64")) {
2042
+ ifstat->tx_bytes = data[i].value.ui64;
2043
+ }
2044
+ else if (strEQ(ptr, "oerrors")) {
2045
+ ifstat->tx_errors = value;
2046
+ }
2047
+ else if (strEQ(ptr, "oflo")) {
2048
+ ifstat->tx_overruns = value;
2049
+ }
2050
+ else if (strEQ(ptr, "opackets")) {
2051
+ if (ifstat->tx_packets == 0) {
2052
+ ifstat->tx_packets = value;
2053
+ }
2054
+ }
2055
+ else if (strEQ(ptr, "opackets64")) {
2056
+ ifstat->tx_packets = data[i].value.ui64;
2057
+ }
2058
+ else if (strEQ(ptr, "toolong_errors")) {
2059
+ ifstat->tx_overruns = value;
2060
+ }
2061
+ break;
2062
+ case 'r':
2063
+ if (strEQ(ptr, "rbytes")) {
2064
+ if (ifstat->rx_bytes == 0) {
2065
+ ifstat->rx_bytes = value;
2066
+ }
2067
+ }
2068
+ else if (strEQ(ptr, "rbytes64")) {
2069
+ ifstat->rx_bytes = data[i].value.ui64;
2070
+ }
2071
+ else if (strEQ(ptr, "rx_overflow")) {
2072
+ ifstat->rx_overruns = value;
2073
+ }
2074
+ break;
2075
+ default:
2076
+ break;
2077
+ }
2078
+ }
2079
+ }
2080
+
2081
+ static int sigar_net_ifstat_get_any(sigar_t *sigar, const char *name,
2082
+ sigar_net_interface_stat_t *ifstat)
2083
+ {
2084
+ kstat_ctl_t *kc = sigar->kc;
2085
+ kstat_t *ksp;
2086
+ kstat_named_t *data;
2087
+
2088
+ if (sigar_kstat_update(sigar) == -1) {
2089
+ return errno;
2090
+ }
2091
+
2092
+ if (!(ksp = kstat_lookup(kc, NULL, -1, (char *)name))) {
2093
+ return ENXIO;
2094
+ }
2095
+
2096
+ if (kstat_read(kc, ksp, NULL) < 0) {
2097
+ return ENOENT;
2098
+ }
2099
+
2100
+ data = (kstat_named_t *)ksp->ks_data;
2101
+
2102
+ ifstat_kstat_common(ifstat, data, ksp->ks_ndata);
2103
+
2104
+ return SIGAR_OK;
2105
+ }
2106
+
2107
+ /* loopback interface only has rx/tx packets */
2108
+ static int sigar_net_ifstat_get_lo(sigar_t *sigar, const char *name,
2109
+ sigar_net_interface_stat_t *ifstat)
2110
+ {
2111
+ ifstat->rx_packets = 0;
2112
+ ifstat->rx_bytes = SIGAR_FIELD_NOTIMPL;
2113
+ ifstat->rx_errors = SIGAR_FIELD_NOTIMPL;
2114
+ ifstat->rx_dropped = SIGAR_FIELD_NOTIMPL;
2115
+ ifstat->rx_overruns = SIGAR_FIELD_NOTIMPL;
2116
+ ifstat->rx_frame = SIGAR_FIELD_NOTIMPL;
2117
+
2118
+ ifstat->tx_packets = 0;
2119
+ ifstat->tx_bytes = SIGAR_FIELD_NOTIMPL;
2120
+ ifstat->tx_errors = SIGAR_FIELD_NOTIMPL;
2121
+ ifstat->tx_dropped = SIGAR_FIELD_NOTIMPL;
2122
+ ifstat->tx_overruns = SIGAR_FIELD_NOTIMPL;
2123
+ ifstat->tx_collisions = SIGAR_FIELD_NOTIMPL;
2124
+ ifstat->tx_carrier = SIGAR_FIELD_NOTIMPL;
2125
+
2126
+ ifstat->speed = SIGAR_FIELD_NOTIMPL;
2127
+
2128
+ return sigar_net_ifstat_get_any(sigar, name, ifstat);
2129
+ }
2130
+
2131
+ int sigar_net_interface_stat_get(sigar_t *sigar, const char *name,
2132
+ sigar_net_interface_stat_t *ifstat)
2133
+ {
2134
+ ifstat->speed = SIGAR_FIELD_NOTIMPL;
2135
+
2136
+ if (strnEQ(name, "lo", 2)) {
2137
+ return sigar_net_ifstat_get_lo(sigar, name, ifstat);
2138
+ }
2139
+ else {
2140
+ SIGAR_ZERO(ifstat);
2141
+ return sigar_net_ifstat_get_any(sigar, name, ifstat);
2142
+ }
2143
+ }
2144
+
2145
+ int sigar_net_interface_ipv6_config_get(sigar_t *sigar, const char *name,
2146
+ sigar_net_interface_config_t *ifconfig)
2147
+ {
2148
+ int sock;
2149
+ struct lifreq lifr;
2150
+
2151
+ if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
2152
+ return errno;
2153
+ }
2154
+
2155
+ SIGAR_SSTRCPY(lifr.lifr_name, name);
2156
+
2157
+ if (ioctl(sock, SIOCGLIFADDR, &lifr) == 0) {
2158
+ struct in6_addr *addr = SIGAR_SIN6_ADDR(&lifr.lifr_addr);
2159
+
2160
+ sigar_net_address6_set(ifconfig->address6, addr);
2161
+ sigar_net_interface_scope6_set(ifconfig, addr);
2162
+ ifconfig->prefix6_length = lifr.lifr_addrlen;
2163
+ }
2164
+
2165
+ close(sock);
2166
+ return SIGAR_OK;
2167
+ }
2168
+
2169
+ #define TCPQ_SIZE(s) ((s) >= 0 ? (s) : 0)
2170
+
2171
+ static int tcp_connection_get(sigar_net_connection_walker_t *walker,
2172
+ struct mib2_tcpConnEntry *entry,
2173
+ int len)
2174
+ {
2175
+ int flags = walker->flags;
2176
+ int status;
2177
+ char *end = (char *)entry + len;
2178
+
2179
+ while ((char *)entry < end) {
2180
+ int state = entry->tcpConnEntryInfo.ce_state;
2181
+
2182
+ if (((flags & SIGAR_NETCONN_SERVER) && (state == TCPS_LISTEN)) ||
2183
+ ((flags & SIGAR_NETCONN_CLIENT) && (state != TCPS_LISTEN)))
2184
+ {
2185
+ sigar_net_connection_t conn;
2186
+
2187
+ SIGAR_ZERO(&conn);
2188
+
2189
+ sigar_net_address_set(conn.local_address, entry->tcpConnLocalAddress);
2190
+ sigar_net_address_set(conn.remote_address, entry->tcpConnRemAddress);
2191
+
2192
+ conn.local_port = entry->tcpConnLocalPort;
2193
+ conn.remote_port = entry->tcpConnRemPort;
2194
+ conn.type = SIGAR_NETCONN_TCP;
2195
+ conn.send_queue =
2196
+ TCPQ_SIZE(entry->tcpConnEntryInfo.ce_snxt -
2197
+ entry->tcpConnEntryInfo.ce_suna - 1);
2198
+ conn.receive_queue =
2199
+ TCPQ_SIZE(entry->tcpConnEntryInfo.ce_rnxt -
2200
+ entry->tcpConnEntryInfo.ce_rack);
2201
+
2202
+ switch (state) {
2203
+ case TCPS_CLOSED:
2204
+ conn.state = SIGAR_TCP_CLOSE;
2205
+ break;
2206
+ case TCPS_IDLE:
2207
+ conn.state = SIGAR_TCP_IDLE;
2208
+ break;
2209
+ case TCPS_BOUND:
2210
+ conn.state = SIGAR_TCP_BOUND;
2211
+ break;
2212
+ case TCPS_LISTEN:
2213
+ conn.state = SIGAR_TCP_LISTEN;
2214
+ break;
2215
+ case TCPS_SYN_SENT:
2216
+ conn.state = SIGAR_TCP_SYN_SENT;
2217
+ break;
2218
+ case TCPS_SYN_RCVD:
2219
+ conn.state = SIGAR_TCP_SYN_RECV;
2220
+ break;
2221
+ case TCPS_ESTABLISHED:
2222
+ conn.state = SIGAR_TCP_ESTABLISHED;
2223
+ break;
2224
+ case TCPS_CLOSE_WAIT:
2225
+ conn.state = SIGAR_TCP_CLOSE_WAIT;
2226
+ break;
2227
+ case TCPS_FIN_WAIT_1:
2228
+ conn.state = SIGAR_TCP_FIN_WAIT1;
2229
+ break;
2230
+ case TCPS_CLOSING:
2231
+ conn.state = SIGAR_TCP_CLOSING;
2232
+ break;
2233
+ case TCPS_LAST_ACK:
2234
+ conn.state = SIGAR_TCP_LAST_ACK;
2235
+ break;
2236
+ case TCPS_FIN_WAIT_2:
2237
+ conn.state = SIGAR_TCP_FIN_WAIT2;
2238
+ break;
2239
+ case TCPS_TIME_WAIT:
2240
+ conn.state = SIGAR_TCP_TIME_WAIT;
2241
+ break;
2242
+ default:
2243
+ conn.state = SIGAR_TCP_UNKNOWN;
2244
+ break;
2245
+ }
2246
+
2247
+ status = walker->add_connection(walker, &conn);
2248
+ if (status != SIGAR_OK) {
2249
+ return status;
2250
+ }
2251
+ }
2252
+
2253
+ entry++;
2254
+ }
2255
+
2256
+ return SIGAR_OK;
2257
+ }
2258
+
2259
+ static int udp_connection_get(sigar_net_connection_walker_t *walker,
2260
+ struct mib2_udpEntry *entry,
2261
+ int len)
2262
+ {
2263
+ int flags = walker->flags;
2264
+ int status;
2265
+ char *end = (char *)entry + len;
2266
+
2267
+ while ((char *)entry < end) {
2268
+ int state = entry->udpEntryInfo.ue_state;
2269
+
2270
+ /* XXX dunno if this state check is right */
2271
+ if (((flags & SIGAR_NETCONN_SERVER) && (state == MIB2_UDP_idle)) ||
2272
+ ((flags & SIGAR_NETCONN_CLIENT) && (state != MIB2_UDP_idle)))
2273
+ {
2274
+ sigar_net_connection_t conn;
2275
+
2276
+ SIGAR_ZERO(&conn);
2277
+
2278
+ sigar_net_address_set(conn.local_address, entry->udpLocalAddress);
2279
+ sigar_net_address_set(conn.remote_address, 0);
2280
+
2281
+ conn.local_port = entry->udpLocalPort;
2282
+ conn.remote_port = 0;
2283
+ conn.type = SIGAR_NETCONN_UDP;
2284
+
2285
+ status = walker->add_connection(walker, &conn);
2286
+ if (status != SIGAR_OK) {
2287
+ return status;
2288
+ }
2289
+ }
2290
+
2291
+ entry++;
2292
+ }
2293
+
2294
+ return SIGAR_OK;
2295
+ }
2296
+
2297
+ int sigar_net_connection_walk(sigar_net_connection_walker_t *walker)
2298
+ {
2299
+ sigar_t *sigar = walker->sigar;
2300
+ int flags = walker->flags;
2301
+ int status;
2302
+ int want_tcp = flags & SIGAR_NETCONN_TCP;
2303
+ int want_udp = flags & SIGAR_NETCONN_UDP;
2304
+ char *data;
2305
+ int len;
2306
+ int rc;
2307
+ struct opthdr *op;
2308
+
2309
+ while ((rc = get_mib2(&sigar->mib2, &op, &data, &len)) == GET_MIB2_OK) {
2310
+ if ((op->level == MIB2_TCP) &&
2311
+ (op->name == MIB2_TCP_13) &&
2312
+ want_tcp)
2313
+ {
2314
+ status =
2315
+ tcp_connection_get(walker,
2316
+ (struct mib2_tcpConnEntry *)data,
2317
+ len);
2318
+ }
2319
+ else if ((op->level == MIB2_UDP) &&
2320
+ (op->name == MIB2_UDP_5) &&
2321
+ want_udp)
2322
+ {
2323
+ status =
2324
+ udp_connection_get(walker,
2325
+ (struct mib2_udpEntry *)data,
2326
+ len);
2327
+ }
2328
+ else {
2329
+ status = SIGAR_OK;
2330
+ }
2331
+
2332
+ if (status != SIGAR_OK) {
2333
+ break;
2334
+ }
2335
+ }
2336
+
2337
+ if (rc != GET_MIB2_EOD) {
2338
+ close_mib2(&sigar->mib2);
2339
+ return SIGAR_EMIB2;
2340
+ }
2341
+
2342
+ return SIGAR_OK;
2343
+ }
2344
+
2345
+ SIGAR_DECLARE(int)
2346
+ sigar_tcp_get(sigar_t *sigar,
2347
+ sigar_tcp_t *tcp)
2348
+ {
2349
+ char *data;
2350
+ int len;
2351
+ int rc;
2352
+ struct opthdr *op;
2353
+ mib2_tcp_t *mib = NULL;
2354
+
2355
+ while ((rc = get_mib2(&sigar->mib2, &op, &data, &len)) == GET_MIB2_OK) {
2356
+ if ((op->level == MIB2_TCP) && (op->name == 0)) {
2357
+ mib = (mib2_tcp_t *)data;
2358
+ break;
2359
+ }
2360
+ }
2361
+
2362
+ if (mib) {
2363
+ tcp->active_opens = mib->tcpActiveOpens;
2364
+ tcp->passive_opens = mib->tcpPassiveOpens;
2365
+ tcp->attempt_fails = mib->tcpAttemptFails;
2366
+ tcp->estab_resets = mib->tcpEstabResets;
2367
+ tcp->curr_estab = mib->tcpCurrEstab;
2368
+ tcp->in_segs = mib->tcpInSegs;
2369
+ tcp->out_segs = mib->tcpOutSegs;
2370
+ tcp->retrans_segs = mib->tcpRetransSegs;
2371
+ tcp->in_errs = SIGAR_FIELD_NOTIMPL; /* XXX mib2_ip_t.tcpInErrs */
2372
+ tcp->out_rsts = mib->tcpOutRsts;
2373
+ return SIGAR_OK;
2374
+ }
2375
+ else {
2376
+ return SIGAR_ENOTIMPL;
2377
+ }
2378
+ }
2379
+
2380
+ static int sigar_nfs_get(sigar_t *sigar,
2381
+ char *type,
2382
+ char **names,
2383
+ char *nfs)
2384
+ {
2385
+ size_t offset;
2386
+ kstat_t *ksp;
2387
+ int i;
2388
+
2389
+ if (sigar_kstat_update(sigar) == -1) {
2390
+ return errno;
2391
+ }
2392
+
2393
+ if (!(ksp = kstat_lookup(sigar->kc, "nfs", 0, type))) {
2394
+ return SIGAR_ENOTIMPL;
2395
+ }
2396
+
2397
+ if (kstat_read(sigar->kc, ksp, NULL) < 0) {
2398
+ return errno;
2399
+ }
2400
+
2401
+ for (i=0, offset=0;
2402
+ names[i];
2403
+ i++, offset+=sizeof(sigar_uint64_t))
2404
+ {
2405
+ sigar_uint64_t val;
2406
+ kstat_named_t *kv =
2407
+ kstat_data_lookup(ksp, names[i]);
2408
+
2409
+ if (kv) {
2410
+ val = kv->value.ui64;
2411
+ }
2412
+ else {
2413
+ val = -1;
2414
+ }
2415
+
2416
+ *(sigar_uint64_t *)((char *)nfs + offset) = val;
2417
+ }
2418
+
2419
+ return SIGAR_OK;
2420
+ }
2421
+
2422
+ static char *nfs_v2_names[] = {
2423
+ "null",
2424
+ "getattr",
2425
+ "setattr",
2426
+ "root",
2427
+ "lookup",
2428
+ "readlink",
2429
+ "read",
2430
+ "wrcache",
2431
+ "write",
2432
+ "create",
2433
+ "remove",
2434
+ "rename",
2435
+ "link",
2436
+ "symlink",
2437
+ "mkdir",
2438
+ "rmdir",
2439
+ "readdir",
2440
+ "statfs",
2441
+ NULL
2442
+ };
2443
+
2444
+ int sigar_nfs_client_v2_get(sigar_t *sigar,
2445
+ sigar_nfs_client_v2_t *nfs)
2446
+ {
2447
+ return sigar_nfs_get(sigar, "rfsreqcnt_v2", nfs_v2_names, (char *)nfs);
2448
+ }
2449
+
2450
+ int sigar_nfs_server_v2_get(sigar_t *sigar,
2451
+ sigar_nfs_server_v2_t *nfs)
2452
+ {
2453
+ return sigar_nfs_get(sigar, "rfsproccnt_v2", nfs_v2_names, (char *)nfs);
2454
+ }
2455
+
2456
+ static char *nfs_v3_names[] = {
2457
+ "null",
2458
+ "getattr",
2459
+ "setattr",
2460
+ "lookup",
2461
+ "access",
2462
+ "readlink",
2463
+ "read",
2464
+ "write",
2465
+ "create",
2466
+ "mkdir",
2467
+ "symlink",
2468
+ "mknod",
2469
+ "remove",
2470
+ "rmdir",
2471
+ "rename",
2472
+ "link",
2473
+ "readdir",
2474
+ "readdirplus",
2475
+ "fsstat",
2476
+ "fsinfo",
2477
+ "pathconf",
2478
+ "commit",
2479
+ NULL
2480
+ };
2481
+
2482
+ int sigar_nfs_client_v3_get(sigar_t *sigar,
2483
+ sigar_nfs_client_v3_t *nfs)
2484
+ {
2485
+ return sigar_nfs_get(sigar, "rfsreqcnt_v3", nfs_v3_names, (char *)nfs);
2486
+ }
2487
+
2488
+ int sigar_nfs_server_v3_get(sigar_t *sigar,
2489
+ sigar_nfs_server_v3_t *nfs)
2490
+ {
2491
+ return sigar_nfs_get(sigar, "rfsproccnt_v3", nfs_v3_names, (char *)nfs);
2492
+ }
2493
+
2494
+ int sigar_arp_list_get(sigar_t *sigar,
2495
+ sigar_arp_list_t *arplist)
2496
+ {
2497
+ char *data;
2498
+ int len, rc;
2499
+ struct opthdr *op;
2500
+ size_t nread=0, size=0;
2501
+ const char *size_from;
2502
+
2503
+ sigar_arp_list_create(arplist);
2504
+
2505
+ while ((rc = get_mib2(&sigar->mib2, &op, &data, &len)) == GET_MIB2_OK) {
2506
+ mib2_ipNetToMediaEntry_t *entry;
2507
+ char *end;
2508
+
2509
+ if (op->level != MIB2_IP) {
2510
+ continue;
2511
+ }
2512
+
2513
+ if (op->name == 0) {
2514
+ /* we want to use this size for bincompat */
2515
+ size = ((mib2_ip_t *)data)->ipNetToMediaEntrySize;
2516
+ continue;
2517
+ }
2518
+ else if (op->name != MIB2_IP_MEDIA) {
2519
+ continue;
2520
+ }
2521
+
2522
+ if (size == 0) {
2523
+ size_from = "sizeof";
2524
+ size = sizeof(*entry);
2525
+ }
2526
+ else {
2527
+ size_from = "mib2_ip";
2528
+ }
2529
+
2530
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
2531
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2532
+ "[arp_list] ipNetToMediaEntrySize=%d (from %s)",
2533
+ size, size_from);
2534
+ }
2535
+
2536
+ for (entry = (mib2_ipNetToMediaEntry_t *)data, end = data + len;
2537
+ (char *)entry < end;
2538
+ nread+=size, entry = (mib2_ipNetToMediaEntry_t *)((char *)data+nread))
2539
+ {
2540
+ sigar_arp_t *arp;
2541
+
2542
+ SIGAR_ARP_LIST_GROW(arplist);
2543
+ arp = &arplist->data[arplist->number++];
2544
+
2545
+ sigar_net_address_set(arp->address,
2546
+ entry->ipNetToMediaNetAddress);
2547
+
2548
+ sigar_net_address_mac_set(arp->hwaddr,
2549
+ entry->ipNetToMediaPhysAddress.o_bytes,
2550
+ entry->ipNetToMediaPhysAddress.o_length);
2551
+
2552
+ SIGAR_SSTRCPY(arp->ifname, entry->ipNetToMediaIfIndex.o_bytes);
2553
+
2554
+ arp->flags = entry->ipNetToMediaInfo.ntm_flags;
2555
+ SIGAR_SSTRCPY(arp->type, "ether"); /*XXX*/
2556
+ }
2557
+ }
2558
+
2559
+ if (rc != GET_MIB2_EOD) {
2560
+ close_mib2(&sigar->mib2);
2561
+ return SIGAR_EMIB2;
2562
+ }
2563
+
2564
+ return SIGAR_OK;
2565
+ }
2566
+
2567
+ static int find_port(sigar_t *sigar, struct ps_prochandle *phandle,
2568
+ sigar_pid_t pid, unsigned long port)
2569
+ {
2570
+ DIR *dirp;
2571
+ struct dirent *ent;
2572
+ char pname[PATH_MAX];
2573
+ struct stat64 statb;
2574
+ int found=0;
2575
+
2576
+ sprintf(pname, "/proc/%d/fd", (int)pid);
2577
+
2578
+ if (!(dirp = opendir(pname))) {
2579
+ return 0;
2580
+ }
2581
+
2582
+ while ((ent = readdir(dirp))) {
2583
+ int fd;
2584
+
2585
+ if (!sigar_isdigit(ent->d_name[0])) {
2586
+ continue;
2587
+ }
2588
+ fd = atoi(ent->d_name);
2589
+
2590
+ if (sigar->pfstat64(phandle, fd, &statb) == -1) {
2591
+ continue;
2592
+ }
2593
+
2594
+ if ((statb.st_mode & S_IFMT) == S_IFSOCK) {
2595
+ struct sockaddr_in sin;
2596
+ struct sockaddr *sa = (struct sockaddr *)&sin;
2597
+ socklen_t len = sizeof(sin);
2598
+ int opt, optsz, rc;
2599
+
2600
+ optsz = sizeof(opt);
2601
+ rc = sigar->pgetsockopt(phandle, fd, SOL_SOCKET, SO_TYPE, &opt, &optsz);
2602
+ if (rc != 0) {
2603
+ continue;
2604
+ }
2605
+ if (opt != SOCK_STREAM) {
2606
+ continue;
2607
+ }
2608
+ optsz = sizeof(opt);
2609
+ rc = sigar->pgetsockopt(phandle, fd, SOL_SOCKET, SO_ACCEPTCONN, &opt, &optsz);
2610
+ if (rc != 0) {
2611
+ continue;
2612
+ }
2613
+ if (opt != SO_ACCEPTCONN) {
2614
+ continue;
2615
+ }
2616
+
2617
+ rc = sigar->pgetsockname(phandle, fd, sa, &len);
2618
+ if (rc != 0) {
2619
+ continue;
2620
+ }
2621
+
2622
+ if ((sa->sa_family == AF_INET) ||
2623
+ (sa->sa_family == AF_INET6))
2624
+ {
2625
+ if (ntohs(sin.sin_port) == port) {
2626
+ found = 1;
2627
+ break;
2628
+ }
2629
+ }
2630
+ }
2631
+ }
2632
+
2633
+ closedir(dirp);
2634
+
2635
+ return found;
2636
+ }
2637
+
2638
+ /* derived from /usr/bin/pfiles.c */
2639
+ int sigar_proc_port_get(sigar_t *sigar, int protocol,
2640
+ unsigned long port, sigar_pid_t *pid)
2641
+ {
2642
+ sigar_proc_list_t pids;
2643
+ int i, status, found=0;
2644
+
2645
+ if (sigar->solaris_version < 10) {
2646
+ return SIGAR_ENOTIMPL;
2647
+ }
2648
+
2649
+ if ((status = sigar_init_libproc(sigar)) != SIGAR_OK) {
2650
+ return SIGAR_ENOTIMPL;
2651
+ }
2652
+ status = sigar_proc_list_get(sigar, &pids);
2653
+ if (status != SIGAR_OK) {
2654
+ return status;
2655
+ }
2656
+
2657
+ for (i=0; i<pids.number; i++) {
2658
+ sigar_pid_t ps_id = pids.data[i];
2659
+ struct ps_prochandle *phandle;
2660
+
2661
+ if (ps_id == sigar_pid_get(sigar)) {
2662
+ continue; /* XXX */
2663
+ }
2664
+ status = sigar_pgrab(sigar, ps_id, SIGAR_FUNC, &phandle);
2665
+
2666
+ if (status != SIGAR_OK) {
2667
+ continue;
2668
+ }
2669
+
2670
+ if (sigar->pcreate_agent(phandle) == 0) {
2671
+ found = find_port(sigar, phandle, ps_id, port);
2672
+ sigar->pdestroy_agent(phandle);
2673
+ }
2674
+
2675
+ sigar->pfree(phandle);
2676
+ if (found) {
2677
+ *pid = ps_id;
2678
+ break;
2679
+ }
2680
+ }
2681
+
2682
+ sigar_proc_list_destroy(sigar, &pids);
2683
+
2684
+ return found ? SIGAR_OK : ENOENT;
2685
+ }
2686
+
2687
+ int sigar_os_sys_info_get(sigar_t *sigar,
2688
+ sigar_sys_info_t *sys_info)
2689
+ {
2690
+ char *vendor_version;
2691
+
2692
+ sysinfo(SI_ARCHITECTURE, sys_info->arch, sizeof(sys_info->arch));
2693
+
2694
+ SIGAR_SSTRCPY(sys_info->name, "Solaris");
2695
+ SIGAR_SSTRCPY(sys_info->vendor, "Sun Microsystems");
2696
+
2697
+ if (strEQ(sys_info->version, "5.6")) {
2698
+ vendor_version = "2.6";
2699
+ }
2700
+ else {
2701
+ if ((vendor_version = strchr(sys_info->version, '.'))) {
2702
+ ++vendor_version;
2703
+ }
2704
+ else {
2705
+ vendor_version = sys_info->version;
2706
+ }
2707
+ }
2708
+
2709
+ SIGAR_SSTRCPY(sys_info->vendor_version, vendor_version);
2710
+
2711
+ snprintf(sys_info->description,
2712
+ sizeof(sys_info->description),
2713
+ "%s %s",
2714
+ sys_info->name, sys_info->vendor_version);
2715
+
2716
+ return SIGAR_OK;
2717
+ }