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,2168 @@
1
+ /*
2
+ * Copyright (c) 2004-2009 Hyperic, Inc.
3
+ * Copyright (c) 2009 SpringSource, Inc.
4
+ * Copyright (c) 2009-2010 VMware, Inc.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ /* pull in time.h before resource.h does w/ _KERNEL */
20
+ #include <sys/time.h>
21
+ #define _KERNEL 1
22
+ #include <sys/file.h> /* for struct file */
23
+ #include <sys/resource.h> /* for rlimit32 in 64-bit mode */
24
+ #undef _KERNEL
25
+
26
+ #include "sigar.h"
27
+ #include "sigar_private.h"
28
+ #include "sigar_util.h"
29
+ #include "sigar_os.h"
30
+
31
+ #include <dlfcn.h>
32
+ #include <nlist.h>
33
+ #include <pthread.h>
34
+ #include <stdio.h>
35
+ #include <utmp.h>
36
+ #include <libperfstat.h>
37
+ #include <pthread.h>
38
+
39
+ #include <sys/statfs.h>
40
+ #include <sys/systemcfg.h>
41
+ #include <sys/sysinfo.h>
42
+ #include <sys/var.h>
43
+ #include <sys/vminfo.h>
44
+ #include <sys/mntctl.h>
45
+ #include <sys/stat.h>
46
+ #include <sys/user.h>
47
+ #include <sys/utsname.h>
48
+ #include <sys/vmount.h>
49
+ #include <sys/proc.h>
50
+
51
+ #include <sys/socket.h>
52
+ #include <arpa/inet.h>
53
+ #include <net/if.h>
54
+
55
+ /* for proc_port */
56
+ #include <netinet/in_pcb.h>
57
+ #include <sys/domain.h>
58
+ #include <sys/protosw.h>
59
+ #include <sys/socketvar.h>
60
+
61
+ /* for net_connection_list */
62
+ #include <netinet/ip_var.h>
63
+ #include <netinet/tcp_timer.h>
64
+ #include <netinet/tcp_var.h>
65
+ #include <netinet/tcp_fsm.h>
66
+
67
+ /* for odm api */
68
+ #include <sys/cfgodm.h>
69
+ #include <sys/cfgdb.h>
70
+ #include <cf.h>
71
+
72
+ #include <sys/ldr.h>
73
+
74
+ /* for net_interface_config ipv6 */
75
+ #include <sys/ioctl.h>
76
+ #include <netinet/in6_var.h>
77
+
78
+ /* for getkerninfo */
79
+ #include <sys/kinfo.h>
80
+
81
+ /* not defined in aix 4.3 */
82
+ #ifndef SBITS
83
+ #define SBITS 16
84
+ #endif
85
+
86
+ #ifndef PTHRDSINFO_RUSAGE_START
87
+ #define PTHRDSINFO_RUSAGE_START 0x00000001
88
+ #define PTHRDSINFO_RUSAGE_STOP 0x00000002
89
+ #define PTHRDSINFO_RUSAGE_COLLECT 0x00000004
90
+ #endif
91
+
92
+ /*
93
+ * from libperfstat.h:
94
+ * "To calculate the load average, divide the numbers by (1<<SBITS).
95
+ * SBITS is defined in <sys/proc.h>."
96
+ */
97
+ #define FIXED_TO_DOUBLE(x) (((double)x) / (1<<SBITS))
98
+
99
+ /* these offsets wont change so just lookup them up during open */
100
+ static int get_koffsets(sigar_t *sigar)
101
+ {
102
+ int i;
103
+ /* see man knlist and nlist.h */
104
+ struct nlist klist[] = {
105
+ {"avenrun", 0, 0, 0, 0, 0}, /* KOFFSET_LOADAVG */
106
+ {"v", 0, 0, 0, 0, 0}, /* KOFFSET_VAR */
107
+ {"sysinfo", 0, 0, 0, 0, 0}, /* KOFFSET_SYSINFO */
108
+ {"ifnet", 0, 0, 0, 0, 0}, /* KOFFSET_IFNET */
109
+ {"vmminfo", 0, 0, 0, 0, 0}, /* KOFFSET_VMINFO */
110
+ {"cpuinfo", 0, 0, 0, 0, 0}, /* KOFFSET_CPUINFO */
111
+ {"tcb", 0, 0, 0, 0, 0}, /* KOFFSET_TCB */
112
+ {"arptabsize", 0, 0, 0, 0, 0}, /* KOFFSET_ARPTABSIZE */
113
+ {"arptabp", 0, 0, 0, 0, 0}, /* KOFFSET_ARPTABP */
114
+ {NULL, 0, 0, 0, 0, 0}
115
+ };
116
+
117
+ if (knlist(klist,
118
+ sizeof(klist) / sizeof(klist[0]),
119
+ sizeof(klist[0])) != 0)
120
+ {
121
+ return errno;
122
+ }
123
+
124
+ for (i=0; i<KOFFSET_MAX; i++) {
125
+ sigar->koffsets[i] = klist[i].n_value;
126
+ }
127
+
128
+ return SIGAR_OK;
129
+ }
130
+
131
+ static int kread(sigar_t *sigar, void *data, int size, long offset)
132
+ {
133
+ if (sigar->kmem < 0) {
134
+ return SIGAR_EPERM_KMEM;
135
+ }
136
+
137
+ if (lseek(sigar->kmem, offset, SEEK_SET) != offset) {
138
+ return errno;
139
+ }
140
+
141
+ if (read(sigar->kmem, data, size) != size) {
142
+ return errno;
143
+ }
144
+
145
+ return SIGAR_OK;
146
+ }
147
+
148
+ static int sigar_thread_rusage(struct rusage *usage, int mode)
149
+ {
150
+ return pthread_getrusage_np(pthread_self(), usage, mode);
151
+ }
152
+
153
+ static int sigar_perfstat_memory(perfstat_memory_total_t *memory)
154
+ {
155
+ return perfstat_memory_total(NULL, memory, sizeof(*memory), 1);
156
+ }
157
+
158
+ static int sigar_perfstat_cpu(perfstat_cpu_total_t *cpu_total)
159
+ {
160
+ return perfstat_cpu_total(NULL, cpu_total, sizeof(*cpu_total), 1);
161
+ }
162
+
163
+ int sigar_os_open(sigar_t **sigar)
164
+ {
165
+ int status, i;
166
+ int kmem = -1;
167
+ struct utsname name;
168
+
169
+ kmem = open("/dev/kmem", O_RDONLY);
170
+
171
+ *sigar = malloc(sizeof(**sigar));
172
+
173
+ (*sigar)->getprocfd = NULL; /*XXX*/
174
+ (*sigar)->kmem = kmem;
175
+ (*sigar)->pagesize = 0;
176
+ (*sigar)->ticks = sysconf(_SC_CLK_TCK);
177
+ (*sigar)->boot_time = 0;
178
+ (*sigar)->last_pid = -1;
179
+ (*sigar)->pinfo = NULL;
180
+ (*sigar)->cpuinfo = NULL;
181
+ (*sigar)->cpuinfo_size = 0;
182
+ SIGAR_ZERO(&(*sigar)->swaps);
183
+
184
+ i = getpagesize();
185
+ while ((i >>= 1) > 0) {
186
+ (*sigar)->pagesize++;
187
+ }
188
+
189
+ if (kmem > 0) {
190
+ if ((status = get_koffsets(*sigar)) != SIGAR_OK) {
191
+ /* libperfstat only mode (aix 6) */
192
+ close((*sigar)->kmem);
193
+ (*sigar)->kmem = -1;
194
+ }
195
+ }
196
+
197
+ (*sigar)->cpu_mhz = -1;
198
+
199
+ (*sigar)->model[0] = '\0';
200
+
201
+ uname(&name);
202
+
203
+ (*sigar)->aix_version = atoi(name.version);
204
+
205
+ (*sigar)->thrusage = PTHRDSINFO_RUSAGE_STOP;
206
+
207
+ (*sigar)->diskmap = NULL;
208
+
209
+ return SIGAR_OK;
210
+ }
211
+
212
+ static void swaps_free(swaps_t *swaps);
213
+
214
+ int sigar_os_close(sigar_t *sigar)
215
+ {
216
+ swaps_free(&sigar->swaps);
217
+ if (sigar->kmem > 0) {
218
+ close(sigar->kmem);
219
+ }
220
+ if (sigar->pinfo) {
221
+ free(sigar->pinfo);
222
+ }
223
+ if (sigar->cpuinfo) {
224
+ free(sigar->cpuinfo);
225
+ }
226
+ if (sigar->diskmap) {
227
+ sigar_cache_destroy(sigar->diskmap);
228
+ }
229
+ if (sigar->thrusage == PTHRDSINFO_RUSAGE_START) {
230
+ struct rusage usage;
231
+ sigar_thread_rusage(&usage,
232
+ PTHRDSINFO_RUSAGE_STOP);
233
+ }
234
+ free(sigar);
235
+ return SIGAR_OK;
236
+ }
237
+
238
+ char *sigar_os_error_string(sigar_t *sigar, int err)
239
+ {
240
+ switch (err) {
241
+ case SIGAR_EPERM_KMEM:
242
+ return "Failed to open /dev/kmem for reading";
243
+ default:
244
+ return NULL;
245
+ }
246
+ }
247
+
248
+ #define PAGESHIFT(v) \
249
+ ((v) << sigar->pagesize)
250
+
251
+ int sigar_mem_get(sigar_t *sigar, sigar_mem_t *mem)
252
+ {
253
+ int status;
254
+ perfstat_memory_total_t minfo;
255
+ sigar_uint64_t kern;
256
+
257
+ if (sigar_perfstat_memory(&minfo) == 1) {
258
+ mem->total = PAGESHIFT(minfo.real_total);
259
+ mem->free = PAGESHIFT(minfo.real_free);
260
+ kern = PAGESHIFT(minfo.numperm); /* number of pages in file cache */
261
+ }
262
+ else {
263
+ return errno;
264
+ }
265
+
266
+ mem->used = mem->total - mem->free;
267
+ mem->actual_used = mem->used - kern;
268
+ mem->actual_free = mem->free + kern;
269
+
270
+ sigar_mem_calc_ram(sigar, mem);
271
+
272
+ return SIGAR_OK;
273
+ }
274
+
275
+ static void swaps_free(swaps_t *swaps)
276
+ {
277
+ if (swaps->num) {
278
+ int i;
279
+
280
+ for (i=0; i<swaps->num; i++) {
281
+ free(swaps->devs[i]);
282
+ }
283
+
284
+ free(swaps->devs);
285
+
286
+ swaps->num = 0;
287
+ }
288
+ }
289
+
290
+ /*
291
+ * there is no public api for parsing this file.
292
+ * well, there is something, but its super ugly and requires
293
+ * linking 2 static libraries (libodm and something else)
294
+ * maybe will switch to that if it can add value elsewhere too.
295
+ */
296
+ #define SWAPSPACES "/etc/swapspaces"
297
+
298
+ static int swaps_get(swaps_t *swaps)
299
+ {
300
+ FILE *fp;
301
+ char buf[512];
302
+ char *ptr;
303
+ struct stat statbuf;
304
+
305
+ if (stat(SWAPSPACES, &statbuf) < 0) {
306
+ return errno;
307
+ }
308
+
309
+ /* only re-parse if file has changed */
310
+ if (swaps->mtime == statbuf.st_mtime) {
311
+ return 0;
312
+ }
313
+
314
+ swaps->mtime = statbuf.st_mtime;
315
+
316
+ /* easier to just start from scratch */
317
+ swaps_free(swaps);
318
+
319
+ if (!(fp = fopen(SWAPSPACES, "r"))) {
320
+ return errno;
321
+ }
322
+
323
+ while ((ptr = fgets(buf, sizeof(buf), fp))) {
324
+ if (!isalpha(*ptr)) {
325
+ continue;
326
+ }
327
+
328
+ if (strchr(ptr, ':')) {
329
+ int len;
330
+
331
+ ptr = fgets(buf, sizeof(buf), fp);
332
+
333
+ while (isspace(*ptr)) {
334
+ ++ptr;
335
+ }
336
+
337
+ if (strncmp(ptr, "dev", 3)) {
338
+ continue;
339
+ }
340
+ ptr += 3;
341
+ while (isspace(*ptr) || (*ptr == '=')) {
342
+ ++ptr;
343
+ }
344
+
345
+ len = strlen(ptr);
346
+ ptr[len-1] = '\0'; /* -1 == chomp \n */
347
+
348
+ swaps->devs = realloc(swaps->devs, swaps->num+1 * sizeof(char *));
349
+ swaps->devs[swaps->num] = malloc(len);
350
+ memcpy(swaps->devs[swaps->num], ptr, len);
351
+
352
+ swaps->num++;
353
+ }
354
+ }
355
+
356
+ fclose(fp);
357
+
358
+ return 0;
359
+ }
360
+
361
+ /*
362
+ * documented in aix tech ref,
363
+ * but this prototype is not in any friggin header file.
364
+ * struct pginfo is in sys/vminfo.h
365
+ */
366
+
367
+ int swapqry(char *path, struct pginfo *info);
368
+
369
+ static int sigar_swap_get_swapqry(sigar_t *sigar, sigar_swap_t *swap)
370
+ {
371
+ int status, i;
372
+
373
+ if ((status = swaps_get(&sigar->swaps)) != SIGAR_OK) {
374
+ return status;
375
+ }
376
+
377
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
378
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
379
+ "[swap] pagesize=%d, shift=%d",
380
+ getpagesize(), sigar->pagesize);
381
+ }
382
+
383
+ swap->total = swap->free = 0;
384
+
385
+ for (i=0; i<sigar->swaps.num; i++) {
386
+ struct pginfo info;
387
+
388
+ status = swapqry(sigar->swaps.devs[i], &info);
389
+
390
+ if (status != 0) {
391
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
392
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
393
+ "[swap] swapqry(%s) failed: %s",
394
+ sigar->swaps.devs[i],
395
+ sigar_strerror(sigar, errno));
396
+ }
397
+ continue;
398
+ }
399
+
400
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
401
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
402
+ "[swap] %s total=%d/%d, free=%d/%d",
403
+ sigar->swaps.devs[i],
404
+ info.size, PAGESHIFT(info.size),
405
+ info.free, PAGESHIFT(info.free));
406
+ }
407
+
408
+ swap->total += PAGESHIFT(info.size); /* lsps -a */
409
+ swap->free += PAGESHIFT(info.free);
410
+ }
411
+
412
+ swap->used = swap->total - swap->free;
413
+
414
+ return SIGAR_OK;
415
+ }
416
+
417
+ #define SWAP_DEV(ps) \
418
+ ((ps.type == LV_PAGING) ? \
419
+ ps.u.lv_paging.vgname : \
420
+ ps.u.nfs_paging.filename)
421
+
422
+ #define SWAP_MB_TO_BYTES(v) ((v) * (1024 * 1024))
423
+
424
+ int sigar_swap_get(sigar_t *sigar, sigar_swap_t *swap)
425
+ {
426
+ perfstat_memory_total_t minfo;
427
+ perfstat_pagingspace_t ps;
428
+ perfstat_id_t id;
429
+
430
+ id.name[0] = '\0';
431
+
432
+ SIGAR_ZERO(swap);
433
+
434
+ do {
435
+ if (perfstat_pagingspace(&id, &ps, sizeof(ps), 1) != 1) {
436
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
437
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
438
+ "[swap] dev=%s query failed: %s",
439
+ SWAP_DEV(ps),
440
+ sigar_strerror(sigar, errno));
441
+ }
442
+ continue;
443
+ }
444
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
445
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
446
+ "[swap] dev=%s: active=%s, "
447
+ "total=%lluMb, used=%lluMb",
448
+ SWAP_DEV(ps),
449
+ ((ps.active == 1) ? "yes" : "no"),
450
+ ps.mb_size, ps.mb_used);
451
+ }
452
+ if (ps.active != 1) {
453
+ continue;
454
+ }
455
+ /* convert MB sizes to bytes */
456
+ swap->total += SWAP_MB_TO_BYTES(ps.mb_size);
457
+ swap->used += SWAP_MB_TO_BYTES(ps.mb_used);
458
+ } while (id.name[0] != '\0');
459
+
460
+ swap->free = swap->total - swap->used;
461
+
462
+ if (sigar_perfstat_memory(&minfo) == 1) {
463
+ swap->page_in = minfo.pgins;
464
+ swap->page_out = minfo.pgouts;
465
+ }
466
+ else {
467
+ swap->page_in = swap->page_out = -1;
468
+ }
469
+ return SIGAR_OK;
470
+ }
471
+
472
+ int sigar_cpu_get(sigar_t *sigar, sigar_cpu_t *cpu)
473
+ {
474
+ int i, status;
475
+ struct sysinfo data;
476
+ perfstat_cpu_total_t cpu_data;
477
+
478
+ if (sigar_perfstat_cpu(&cpu_data) == 1) {
479
+ cpu->user = SIGAR_TICK2MSEC(cpu_data.user);
480
+ cpu->nice = SIGAR_FIELD_NOTIMPL; /* N/A */
481
+ cpu->sys = SIGAR_TICK2MSEC(cpu_data.sys);
482
+ cpu->idle = SIGAR_TICK2MSEC(cpu_data.idle);
483
+ cpu->wait = SIGAR_TICK2MSEC(cpu_data.wait);
484
+ cpu->irq = 0; /*N/A*/
485
+ cpu->soft_irq = 0; /*N/A*/
486
+ cpu->stolen = 0; /*N/A*/
487
+ cpu->total = cpu->user + cpu->sys + cpu->idle + cpu->wait;
488
+ return SIGAR_OK;
489
+ }
490
+ else {
491
+ return errno;
492
+ }
493
+ }
494
+
495
+ /*
496
+ * other possible metrics we could add:
497
+ * struct cpuinfo {
498
+ * long cpu[CPU_NTIMES];
499
+ * long pswitch;
500
+ * long syscall;
501
+ * long sysread;
502
+ * long syswrite;
503
+ * long sysfork;
504
+ * long sysexec;
505
+ * long readch;
506
+ * long writech;
507
+ * long iget;
508
+ * long namei;
509
+ * long dirblk;
510
+ * long msg;
511
+ * long sema;
512
+ * long bread;
513
+ * long bwrite;
514
+ * long lread;
515
+ * long lwrite;
516
+ * long phread;
517
+ * long phwrite;
518
+ * };
519
+ */
520
+
521
+ int sigar_cpu_list_get(sigar_t *sigar, sigar_cpu_list_t *cpulist)
522
+ {
523
+ perfstat_cpu_t data;
524
+ int i, ncpu = _system_configuration.ncpus; /* this can change */
525
+ perfstat_id_t id;
526
+
527
+ id.name[0] = '\0';
528
+
529
+ sigar_cpu_list_create(cpulist);
530
+
531
+ for (i=0; i<ncpu; i++) {
532
+ sigar_cpu_t *cpu;
533
+
534
+ SIGAR_CPU_LIST_GROW(cpulist);
535
+
536
+ cpu = &cpulist->data[cpulist->number++];
537
+
538
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
539
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
540
+ "cpu%d perfstat_id='%s'",
541
+ i, id.name);
542
+ }
543
+
544
+ if (perfstat_cpu(&id, &data, sizeof(data), 1) == 1) {
545
+ cpu->user = SIGAR_TICK2MSEC(data.user);
546
+ cpu->nice = SIGAR_FIELD_NOTIMPL; /* N/A */
547
+ cpu->sys = SIGAR_TICK2MSEC(data.sys);
548
+ cpu->idle = SIGAR_TICK2MSEC(data.idle);
549
+ cpu->wait = SIGAR_TICK2MSEC(data.wait);
550
+ cpu->irq = 0; /*N/A*/
551
+ cpu->soft_irq = 0; /*N/A*/
552
+ cpu->stolen = 0; /*N/A*/
553
+ cpu->total = cpu->user + cpu->sys + cpu->idle + cpu->wait;
554
+ }
555
+ else {
556
+ sigar_log_printf(sigar, SIGAR_LOG_ERROR,
557
+ "cpu%d perfstat_cpu(%s) failed: %s",
558
+ i, id.name, sigar_strerror(sigar, errno));
559
+ SIGAR_ZERO(cpu);
560
+ }
561
+ }
562
+
563
+ return SIGAR_OK;
564
+ }
565
+
566
+ static int boot_time(sigar_t *sigar, time_t *time)
567
+ {
568
+ int fd;
569
+ struct utmp data;
570
+
571
+ if ((fd = open(UTMP_FILE, O_RDONLY)) < 0) {
572
+ return errno;
573
+ }
574
+
575
+ do {
576
+ if (read(fd, &data, sizeof(data)) != sizeof(data)) {
577
+ int status = errno;
578
+ close(fd);
579
+ return status;
580
+ }
581
+ } while (data.ut_type != BOOT_TIME);
582
+
583
+ *time = data.ut_time;
584
+
585
+ close(fd);
586
+
587
+ return SIGAR_OK;
588
+ }
589
+
590
+ int sigar_uptime_get(sigar_t *sigar,
591
+ sigar_uptime_t *uptime)
592
+ {
593
+ if (sigar->boot_time == 0) {
594
+ int status;
595
+ time_t time;
596
+
597
+ if ((status = boot_time(sigar, &time)) != SIGAR_OK) {
598
+ return status;
599
+ }
600
+
601
+ sigar->boot_time = time;
602
+ }
603
+
604
+ uptime->uptime = time(NULL) - sigar->boot_time;
605
+
606
+ return SIGAR_OK;
607
+ }
608
+
609
+ #define WHOCPY(dest, src) \
610
+ SIGAR_SSTRCPY(dest, src); \
611
+ if (sizeof(src) < sizeof(dest)) \
612
+ dest[sizeof(dest)-1] = '\0'
613
+
614
+ static int sigar_who_utmp(sigar_t *sigar,
615
+ sigar_who_list_t *wholist)
616
+ {
617
+ struct utmp ut;
618
+ FILE *fp;
619
+
620
+ if (!(fp = fopen(UTMP_FILE, "r"))) {
621
+ return errno;
622
+ }
623
+
624
+ while (fread(&ut, sizeof(ut), 1, fp) == 1) {
625
+ sigar_who_t *who;
626
+
627
+ if (*ut.ut_name == '\0') {
628
+ continue;
629
+ }
630
+
631
+ if (ut.ut_type != USER_PROCESS) {
632
+ continue;
633
+ }
634
+
635
+ SIGAR_WHO_LIST_GROW(wholist);
636
+ who = &wholist->data[wholist->number++];
637
+
638
+ WHOCPY(who->user, ut.ut_user);
639
+ WHOCPY(who->device, ut.ut_line);
640
+ WHOCPY(who->host, ut.ut_host);
641
+
642
+ who->time = ut.ut_time;
643
+ }
644
+
645
+ fclose(fp);
646
+
647
+ return SIGAR_OK;
648
+ }
649
+
650
+ int sigar_who_list_get(sigar_t *sigar,
651
+ sigar_who_list_t *wholist)
652
+ {
653
+ int status;
654
+
655
+ sigar_who_list_create(wholist);
656
+
657
+ status = sigar_who_utmp(sigar, wholist);
658
+ if (status != SIGAR_OK) {
659
+ sigar_who_list_destroy(sigar, wholist);
660
+ return status;
661
+ }
662
+
663
+ return SIGAR_OK;
664
+ }
665
+
666
+ int sigar_loadavg_get(sigar_t *sigar,
667
+ sigar_loadavg_t *loadavg)
668
+ {
669
+ int status, i;
670
+ int data[3];
671
+ perfstat_cpu_total_t cpu_data;
672
+
673
+ if (sigar_perfstat_cpu(&cpu_data) == 1) {
674
+ for (i=0; i<3; i++) {
675
+ loadavg->loadavg[i] = FIXED_TO_DOUBLE(cpu_data.loadavg[i]);
676
+ }
677
+ return SIGAR_OK;
678
+ }
679
+ else {
680
+ return errno;
681
+ }
682
+ }
683
+
684
+ int sigar_os_proc_list_get(sigar_t *sigar,
685
+ sigar_proc_list_t *proclist)
686
+ {
687
+ pid_t pid = 0;
688
+ struct procsinfo info;
689
+
690
+ for (;;) {
691
+ int num = getprocs(&info, sizeof(info),
692
+ NULL, 0, &pid, 1);
693
+
694
+ if (num == 0) {
695
+ break;
696
+ }
697
+
698
+ SIGAR_PROC_LIST_GROW(proclist);
699
+
700
+ proclist->data[proclist->number++] = info.pi_pid;
701
+ }
702
+
703
+ return SIGAR_OK;
704
+ }
705
+
706
+ static int sigar_getprocs(sigar_t *sigar, sigar_pid_t pid)
707
+ {
708
+ int status, num;
709
+ time_t timenow = time(NULL);
710
+
711
+ if (sigar->pinfo == NULL) {
712
+ sigar->pinfo = malloc(sizeof(*sigar->pinfo));
713
+ }
714
+
715
+ if (sigar->last_pid == pid) {
716
+ if ((timenow - sigar->last_getprocs) < SIGAR_LAST_PROC_EXPIRE) {
717
+ return SIGAR_OK;
718
+ }
719
+ }
720
+
721
+ sigar->last_pid = pid;
722
+ sigar->last_getprocs = timenow;
723
+
724
+ num = getprocs(sigar->pinfo, sizeof(*sigar->pinfo),
725
+ NULL, 0, &pid, 1);
726
+
727
+ if (num != 1) {
728
+ return ESRCH;
729
+ }
730
+
731
+ return SIGAR_OK;
732
+ }
733
+
734
+ int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
735
+ sigar_proc_mem_t *procmem)
736
+ {
737
+ int status = sigar_getprocs(sigar, pid);
738
+ struct procsinfo64 *pinfo = sigar->pinfo;
739
+
740
+ if (status != SIGAR_OK) {
741
+ return status;
742
+ }
743
+
744
+ procmem->size = PAGESHIFT(pinfo->pi_size); /* XXX fold in pi_dvm ? */
745
+ procmem->share = PAGESHIFT(pinfo->pi_sdsize);
746
+ procmem->resident = PAGESHIFT(pinfo->pi_drss + pinfo->pi_trss);
747
+
748
+ procmem->minor_faults = pinfo->pi_minflt;
749
+ procmem->major_faults = pinfo->pi_majflt;
750
+ procmem->page_faults =
751
+ procmem->minor_faults +
752
+ procmem->major_faults;
753
+
754
+ return SIGAR_OK;
755
+ }
756
+
757
+ int sigar_proc_cumulative_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
758
+ sigar_proc_cumulative_disk_io_t *cumulative_proc_disk_io)
759
+ {
760
+ int status = sigar_getprocs(sigar, pid);
761
+ struct procsinfo64 *pinfo = sigar->pinfo;
762
+
763
+ if (status != SIGAR_OK) {
764
+ return status;
765
+ }
766
+ cumulative_proc_disk_io->bytes_read = SIGAR_FIELD_NOTIMPL;
767
+ cumulative_proc_disk_io->bytes_written = SIGAR_FIELD_NOTIMPL;
768
+ cumulative_proc_disk_io->bytes_total = pinfo->pi_ioch;
769
+
770
+ return SIGAR_OK;
771
+ }
772
+
773
+
774
+ int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid,
775
+ sigar_proc_cred_t *proccred)
776
+ {
777
+ int status = sigar_getprocs(sigar, pid);
778
+ struct procsinfo64 *pinfo = sigar->pinfo;
779
+
780
+ if (status != SIGAR_OK) {
781
+ return status;
782
+ }
783
+
784
+ proccred->uid = pinfo->pi_cred.cr_ruid;
785
+ proccred->euid = pinfo->pi_cred.cr_uid;
786
+ if (proccred->uid == -1) {
787
+ /*
788
+ * aix 5.2 has a process named 'jfsz'
789
+ * where uid is '-1', getpwuid returns EPERM
790
+ */
791
+ proccred->uid = proccred->euid = 0;
792
+ }
793
+ proccred->gid = pinfo->pi_cred.cr_rgid;
794
+ proccred->egid = pinfo->pi_cred.cr_gid;
795
+
796
+ return SIGAR_OK;
797
+ }
798
+
799
+ int sigar_proc_time_get(sigar_t *sigar, sigar_pid_t pid,
800
+ sigar_proc_time_t *proctime)
801
+ {
802
+ int status = sigar_getprocs(sigar, pid);
803
+ struct procsinfo64 *pinfo = sigar->pinfo;
804
+
805
+ if (status != SIGAR_OK) {
806
+ return status;
807
+ }
808
+
809
+ proctime->start_time = pinfo->pi_start;
810
+ proctime->start_time *= SIGAR_MSEC; /* convert to ms */
811
+ proctime->user = pinfo->pi_utime * SIGAR_MSEC;
812
+ proctime->sys = pinfo->pi_stime * SIGAR_MSEC;
813
+ proctime->total = proctime->user + proctime->sys;
814
+
815
+ return SIGAR_OK;
816
+ }
817
+
818
+ int sigar_proc_state_get(sigar_t *sigar, sigar_pid_t pid,
819
+ sigar_proc_state_t *procstate)
820
+ {
821
+ int status = sigar_getprocs(sigar, pid);
822
+ struct procsinfo64 *pinfo = sigar->pinfo;
823
+ tid_t tid = 0;
824
+ struct thrdsinfo64 thrinfo;
825
+
826
+ if (status != SIGAR_OK) {
827
+ return status;
828
+ }
829
+
830
+ if (getthrds(pid, &thrinfo, sizeof(thrinfo), &tid, 1) == 1) {
831
+ procstate->processor = thrinfo.ti_affinity;
832
+ }
833
+ else {
834
+ procstate->processor = SIGAR_FIELD_NOTIMPL;
835
+ }
836
+
837
+ SIGAR_SSTRCPY(procstate->name, pinfo->pi_comm);
838
+ procstate->ppid = pinfo->pi_ppid;
839
+ procstate->nice = pinfo->pi_nice;
840
+ procstate->tty = pinfo->pi_ttyd;
841
+ procstate->priority = pinfo->pi_pri;
842
+ procstate->threads = pinfo->pi_thcount;
843
+
844
+ switch (pinfo->pi_state) {
845
+ case SACTIVE:
846
+ procstate->state = 'R';
847
+ break;
848
+ case SIDL:
849
+ procstate->state = 'D';
850
+ break;
851
+ case SSTOP:
852
+ procstate->state = 'S';
853
+ break;
854
+ case SZOMB:
855
+ procstate->state = 'Z';
856
+ break;
857
+ case SSWAP:
858
+ procstate->state = 'S';
859
+ break;
860
+ }
861
+
862
+ return SIGAR_OK;
863
+ }
864
+
865
+ int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid,
866
+ sigar_proc_args_t *procargs)
867
+ {
868
+ /* XXX if buffer is not large enough args are truncated */
869
+ char buffer[8192], *ptr;
870
+ struct procsinfo pinfo;
871
+
872
+ pinfo.pi_pid = pid;
873
+
874
+ if (getargs(&pinfo, sizeof(pinfo),
875
+ buffer, sizeof(buffer)) != 0)
876
+ {
877
+ return errno;
878
+ }
879
+
880
+ ptr = buffer;
881
+
882
+ while (*ptr) {
883
+ int alen = strlen(ptr)+1;
884
+ char *arg = malloc(alen);
885
+
886
+ SIGAR_PROC_ARGS_GROW(procargs);
887
+ memcpy(arg, ptr, alen);
888
+
889
+ procargs->data[procargs->number++] = arg;
890
+
891
+ ptr += alen;
892
+ }
893
+
894
+ return SIGAR_OK;
895
+ }
896
+
897
+ int sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid,
898
+ sigar_proc_env_t *procenv)
899
+ {
900
+ /* XXX if buffer is not large enough args are truncated */
901
+ char buffer[8192], *ptr;
902
+ struct procsinfo pinfo;
903
+
904
+ pinfo.pi_pid = pid;
905
+
906
+ if (getevars(&pinfo, sizeof(pinfo),
907
+ buffer, sizeof(buffer)) != 0)
908
+ {
909
+ return errno;
910
+ }
911
+
912
+ ptr = buffer;
913
+
914
+ while (*ptr) {
915
+ char *val = strchr(ptr, '=');
916
+ int klen, vlen, status;
917
+ char key[128]; /* XXX is there a max key size? */
918
+
919
+ if (val == NULL) {
920
+ /* not key=val format */
921
+ procenv->env_getter(procenv->data, ptr, strlen(ptr), NULL, 0);
922
+ break;
923
+ }
924
+
925
+ klen = val - ptr;
926
+ SIGAR_SSTRCPY(key, ptr);
927
+ key[klen] = '\0';
928
+ ++val;
929
+
930
+ vlen = strlen(val);
931
+ status = procenv->env_getter(procenv->data,
932
+ key, klen, val, vlen);
933
+
934
+ if (status != SIGAR_OK) {
935
+ /* not an error; just stop iterating */
936
+ break;
937
+ }
938
+
939
+ ptr += (klen + 1 + vlen + 1);
940
+ }
941
+
942
+ return SIGAR_OK;
943
+ }
944
+
945
+ int sigar_proc_fd_get(sigar_t *sigar, sigar_pid_t pid,
946
+ sigar_proc_fd_t *procfd)
947
+ {
948
+ #ifdef SIGAR_64BIT
949
+ /* XXX no getuser() in 64-bit mode */
950
+ return SIGAR_ENOTIMPL;
951
+ #else
952
+ int i;
953
+ struct procsinfo pinfo;
954
+ struct user uinfo;
955
+
956
+ procfd->total = 0;
957
+ pinfo.pi_pid = pid;
958
+
959
+ if (getuser(&pinfo, sizeof(pinfo),
960
+ &uinfo, sizeof(uinfo)) != 0) {
961
+ if (errno == EINVAL) {
962
+ return SIGAR_ENOTIMPL; /*XXX 5.2+*/
963
+ }
964
+ }
965
+
966
+ /* see sys/user.h */
967
+ for (i=0; i<uinfo.U_maxofile; i++) {
968
+ if (uinfo.U_ofile(i)) {
969
+ procfd->total++;
970
+ }
971
+ }
972
+
973
+ return SIGAR_OK;
974
+ #endif
975
+ }
976
+
977
+ int sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid,
978
+ sigar_proc_exe_t *procexe)
979
+ {
980
+ int len;
981
+ char buffer[8192];
982
+ struct procsinfo pinfo;
983
+
984
+ pinfo.pi_pid = pid;
985
+
986
+ if (getargs(&pinfo, sizeof(pinfo),
987
+ buffer, sizeof(buffer)) != 0)
988
+ {
989
+ return errno;
990
+ }
991
+ /* XXX argv[0] might be relative */
992
+ len = strlen(buffer);
993
+ SIGAR_SSTRCPY(procexe->name, buffer);
994
+
995
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/cwd");
996
+
997
+ if ((len = readlink(buffer, procexe->cwd,
998
+ sizeof(procexe->cwd)-1)) < 0)
999
+ {
1000
+ return errno;
1001
+ }
1002
+ procexe->cwd[len] = '\0';
1003
+
1004
+ procexe->root[0] = '\0';
1005
+
1006
+ return SIGAR_OK;
1007
+ }
1008
+
1009
+ static int sigar_proc_modules_local_get(sigar_t *sigar,
1010
+ sigar_proc_modules_t *procmods)
1011
+ {
1012
+ struct ld_info *info;
1013
+ char *buffer;
1014
+ int size = 2048, status;
1015
+ unsigned int offset;
1016
+
1017
+ buffer = malloc(size);
1018
+ while ((loadquery(L_GETINFO, buffer, size) == -1) &&
1019
+ (errno == ENOMEM))
1020
+ {
1021
+ size += 2048;
1022
+ buffer = realloc(buffer, size);
1023
+ }
1024
+
1025
+ info = (struct ld_info *)buffer;
1026
+
1027
+ do {
1028
+ char *name = info->ldinfo_filename;
1029
+
1030
+ status =
1031
+ procmods->module_getter(procmods->data, name, strlen(name));
1032
+
1033
+ if (status != SIGAR_OK) {
1034
+ /* not an error; just stop iterating */
1035
+ free(buffer);
1036
+ return status;
1037
+ }
1038
+
1039
+ offset = info->ldinfo_next;
1040
+ info = (struct ld_info *)((char*)info + offset);
1041
+ } while(offset);
1042
+
1043
+ free(buffer);
1044
+
1045
+ return SIGAR_OK;
1046
+ }
1047
+
1048
+ int sigar_proc_modules_get(sigar_t *sigar, sigar_pid_t pid,
1049
+ sigar_proc_modules_t *procmods)
1050
+ {
1051
+ if (pid == sigar_pid_get(sigar)) {
1052
+ return sigar_proc_modules_local_get(sigar, procmods);
1053
+ }
1054
+ else {
1055
+ return SIGAR_ENOTIMPL;
1056
+ }
1057
+ }
1058
+
1059
+ #define SIGAR_MICROSEC2NANO(s) \
1060
+ ((sigar_uint64_t)(s) * (sigar_uint64_t)1000)
1061
+
1062
+ #define TIME_NSEC(t) \
1063
+ (SIGAR_SEC2NANO((t).tv_sec) + SIGAR_MICROSEC2NANO((t).tv_usec))
1064
+
1065
+ int sigar_thread_cpu_get(sigar_t *sigar,
1066
+ sigar_uint64_t id,
1067
+ sigar_thread_cpu_t *cpu)
1068
+ {
1069
+ struct rusage usage;
1070
+ int retval;
1071
+
1072
+ if (sigar->thrusage != PTHRDSINFO_RUSAGE_START) {
1073
+ sigar->thrusage = PTHRDSINFO_RUSAGE_START;
1074
+ retval =
1075
+ sigar_thread_rusage(&usage,
1076
+ PTHRDSINFO_RUSAGE_START);
1077
+ if (retval != 0) {
1078
+ return retval;
1079
+ }
1080
+ }
1081
+
1082
+ retval =
1083
+ sigar_thread_rusage(&usage,
1084
+ PTHRDSINFO_RUSAGE_COLLECT);
1085
+ if (retval != 0) {
1086
+ return retval;
1087
+ }
1088
+
1089
+ cpu->user = TIME_NSEC(usage.ru_utime);
1090
+ cpu->sys = TIME_NSEC(usage.ru_stime);
1091
+ cpu->total = TIME_NSEC(usage.ru_utime) + TIME_NSEC(usage.ru_stime);
1092
+
1093
+ return SIGAR_OK;
1094
+ }
1095
+
1096
+ int sigar_os_fs_type_get(sigar_file_system_t *fsp)
1097
+ {
1098
+ return fsp->type;
1099
+ }
1100
+
1101
+ #ifndef MNT_NFS4
1102
+ /* another one documented in aix tech ref
1103
+ * with no friggin prototype in any header file...
1104
+ * ...but added in 5.2
1105
+ */
1106
+ int mntctl(int command, int size, char *buffer);
1107
+ #endif
1108
+
1109
+ int sigar_file_system_list_get(sigar_t *sigar,
1110
+ sigar_file_system_list_t *fslist)
1111
+ {
1112
+ int i, size, num;
1113
+ char *buf, *mntlist;
1114
+
1115
+ /* get required size */
1116
+ if (mntctl(MCTL_QUERY, sizeof(size), (char *)&size) < 0) {
1117
+ return errno;
1118
+ }
1119
+
1120
+ mntlist = buf = malloc(size);
1121
+
1122
+ if ((num = mntctl(MCTL_QUERY, size, buf)) < 0) {
1123
+ free(buf);
1124
+ return errno;
1125
+ }
1126
+
1127
+ sigar_file_system_list_create(fslist);
1128
+
1129
+ for (i=0; i<num; i++) {
1130
+ char *devname;
1131
+ const char *typename = NULL;
1132
+ sigar_file_system_t *fsp;
1133
+ struct vmount *ent = (struct vmount *)mntlist;
1134
+
1135
+ mntlist += ent->vmt_length;
1136
+
1137
+ SIGAR_FILE_SYSTEM_LIST_GROW(fslist);
1138
+
1139
+ fsp = &fslist->data[fslist->number++];
1140
+
1141
+ switch (ent->vmt_gfstype) {
1142
+ case MNT_AIX:
1143
+ typename = "aix";
1144
+ fsp->type = SIGAR_FSTYPE_LOCAL_DISK;
1145
+ break;
1146
+ case MNT_JFS:
1147
+ typename = "jfs";
1148
+ fsp->type = SIGAR_FSTYPE_LOCAL_DISK;
1149
+ break;
1150
+ case MNT_NFS:
1151
+ case MNT_NFS3:
1152
+ typename = "nfs";
1153
+ fsp->type = SIGAR_FSTYPE_NETWORK;
1154
+ break;
1155
+ case MNT_CDROM:
1156
+ fsp->type = SIGAR_FSTYPE_CDROM;
1157
+ break;
1158
+ case MNT_SFS:
1159
+ case MNT_CACHEFS:
1160
+ case MNT_AUTOFS:
1161
+ default:
1162
+ if (ent->vmt_flags & MNT_REMOTE) {
1163
+ fsp->type = SIGAR_FSTYPE_NETWORK;
1164
+ }
1165
+ else {
1166
+ fsp->type = SIGAR_FSTYPE_NONE;
1167
+ }
1168
+ }
1169
+
1170
+ SIGAR_SSTRCPY(fsp->dir_name, vmt2dataptr(ent, VMT_STUB));
1171
+ SIGAR_SSTRCPY(fsp->options, vmt2dataptr(ent, VMT_ARGS));
1172
+
1173
+ devname = vmt2dataptr(ent, VMT_OBJECT);
1174
+
1175
+ if (fsp->type == SIGAR_FSTYPE_NETWORK) {
1176
+ char *hostname = vmt2dataptr(ent, VMT_HOSTNAME);
1177
+ #if 0
1178
+ /* XXX: these do not seem reliable */
1179
+ int hostname_len = vmt2datasize(ent, VMT_HOSTNAME)-1; /* -1 == skip '\0' */
1180
+ int devname_len = vmt2datasize(ent, VMT_OBJECT); /* includes '\0' */
1181
+ #else
1182
+ int hostname_len = strlen(hostname);
1183
+ int devname_len = strlen(devname) + 1;
1184
+ #endif
1185
+ int total_len = hostname_len + devname_len + 1; /* 1 == strlen(":") */
1186
+
1187
+ if (total_len > sizeof(fsp->dev_name)) {
1188
+ /* justincase - prevent overflow. chances: slim..none */
1189
+ SIGAR_SSTRCPY(fsp->dev_name, devname);
1190
+ }
1191
+ else {
1192
+ /* sprintf(fsp->devname, "%s:%s", hostname, devname) */
1193
+ char *ptr = fsp->dev_name;
1194
+
1195
+ memcpy(ptr, hostname, hostname_len);
1196
+ ptr += hostname_len;
1197
+
1198
+ *ptr++ = ':';
1199
+
1200
+ memcpy(ptr, devname, devname_len);
1201
+ }
1202
+ }
1203
+ else {
1204
+ SIGAR_SSTRCPY(fsp->dev_name, devname);
1205
+ }
1206
+
1207
+ /* we set fsp->type, just looking up sigar.c:fstype_names[type] */
1208
+ sigar_fs_type_get(fsp);
1209
+
1210
+ if (typename == NULL) {
1211
+ typename = fsp->type_name;
1212
+ }
1213
+
1214
+ SIGAR_SSTRCPY(fsp->sys_type_name, typename);
1215
+ }
1216
+
1217
+ free(buf);
1218
+
1219
+ return SIGAR_OK;
1220
+ }
1221
+
1222
+ typedef struct {
1223
+ char name[IDENTIFIER_LENGTH];
1224
+ long addr;
1225
+ } aix_diskio_t;
1226
+
1227
+ static int create_diskmap(sigar_t *sigar)
1228
+ {
1229
+ int i, total, num;
1230
+ perfstat_disk_t *disk;
1231
+ perfstat_id_t id;
1232
+
1233
+ total = perfstat_disk(NULL, NULL, sizeof(*disk), 0);
1234
+ if (total < 1) {
1235
+ return ENOENT;
1236
+ }
1237
+
1238
+ disk = malloc(total * sizeof(*disk));
1239
+ id.name[0] = '\0';
1240
+
1241
+ num = perfstat_disk(&id, disk, sizeof(*disk), total);
1242
+ if (num < 1) {
1243
+ free(disk);
1244
+ return ENOENT;
1245
+ }
1246
+
1247
+ sigar->diskmap = sigar_cache_new(25);
1248
+
1249
+ odm_initialize();
1250
+
1251
+ for (i=0; i<num; i++) {
1252
+ char query[256];
1253
+ struct CuDv *dv, *ptr;
1254
+ struct listinfo info;
1255
+ sigar_cache_entry_t *ent;
1256
+ int j;
1257
+
1258
+ snprintf(query, sizeof(query),
1259
+ "parent = '%s'", disk[i].vgname);
1260
+
1261
+ ptr = dv = odm_get_list(CuDv_CLASS, query, &info, 256, 1);
1262
+ if ((int)dv == -1) {
1263
+ continue; /* XXX */
1264
+ }
1265
+
1266
+ for (j=0; j<info.num; j++, ptr++) {
1267
+ struct CuAt *attr;
1268
+ int num, retval;
1269
+ struct stat sb;
1270
+
1271
+ if ((attr = getattr(ptr->name, "label", 0, &num))) {
1272
+ retval = stat(attr->value, &sb);
1273
+
1274
+ if (retval == 0) {
1275
+ aix_diskio_t *diskio = malloc(sizeof(*diskio));
1276
+ SIGAR_SSTRCPY(diskio->name, disk[i].name);
1277
+ diskio->addr = -1;
1278
+ ent = sigar_cache_get(sigar->diskmap, SIGAR_FSDEV_ID(sb));
1279
+ ent->value = diskio;
1280
+ }
1281
+
1282
+ free(attr);
1283
+ }
1284
+ }
1285
+
1286
+ odm_free_list(dv, &info);
1287
+ }
1288
+
1289
+ free(disk);
1290
+ odm_terminate();
1291
+
1292
+ return SIGAR_OK;
1293
+ }
1294
+
1295
+ int sigar_disk_usage_get(sigar_t *sigar, const char *name,
1296
+ sigar_disk_usage_t *usage)
1297
+ {
1298
+ perfstat_disk_t disk;
1299
+ perfstat_id_t id;
1300
+
1301
+ SIGAR_SSTRCPY(id.name, name);
1302
+
1303
+ if (perfstat_disk(&id, &disk, sizeof(disk), 1) != 1) {
1304
+ return ENXIO;
1305
+ }
1306
+
1307
+ usage->reads = disk.rblks;
1308
+ usage->writes = disk.wblks;
1309
+ usage->read_bytes = disk.rblks * disk.bsize;
1310
+ usage->write_bytes = disk.wblks * disk.bsize;
1311
+ usage->queue = disk.qdepth;
1312
+ usage->time = disk.time;
1313
+ usage->rtime = SIGAR_FIELD_NOTIMPL;
1314
+ usage->wtime = SIGAR_FIELD_NOTIMPL;
1315
+
1316
+ return SIGAR_OK;
1317
+ }
1318
+
1319
+ int sigar_file_system_usage_get(sigar_t *sigar,
1320
+ const char *dirname,
1321
+ sigar_file_system_usage_t *fsusage)
1322
+ {
1323
+ sigar_cache_entry_t *ent;
1324
+ struct stat sb;
1325
+ int status;
1326
+
1327
+ status = sigar_statvfs(sigar, dirname, fsusage);
1328
+
1329
+ if (status != SIGAR_OK) {
1330
+ return status;
1331
+ }
1332
+
1333
+ fsusage->use_percent = sigar_file_system_usage_calc_used(sigar, fsusage);
1334
+
1335
+ SIGAR_DISK_STATS_INIT(&fsusage->disk);
1336
+
1337
+ if (!sigar->diskmap) {
1338
+ status = create_diskmap(sigar);
1339
+ if (status != SIGAR_OK) {
1340
+ return SIGAR_OK;
1341
+ }
1342
+ }
1343
+
1344
+ status = stat(dirname, &sb);
1345
+ if (status == 0) {
1346
+ sigar_cache_entry_t *ent =
1347
+ sigar_cache_get(sigar->diskmap, SIGAR_FSDEV_ID(sb));
1348
+ if (!ent->value) {
1349
+ return SIGAR_OK;
1350
+ }
1351
+ sigar_disk_usage_get(sigar, ((aix_diskio_t *)ent->value)->name, &fsusage->disk);
1352
+ }
1353
+
1354
+ return SIGAR_OK;
1355
+ }
1356
+
1357
+ /* from sys/systemcfg.h, not defined in 4.3 headers */
1358
+ #ifndef POWER_4
1359
+ #define POWER_4 0x0800
1360
+ #endif
1361
+ #ifndef POWER_MPC7450
1362
+ #define POWER_MPC7450 0x1000
1363
+ #endif
1364
+ #ifndef POWER_5
1365
+ #define POWER_5 0x2000
1366
+ #endif
1367
+
1368
+ static char *sigar_get_odm_model(sigar_t *sigar)
1369
+ {
1370
+ if (sigar->model[0] == '\0') {
1371
+ struct CuAt *odm_obj;
1372
+ int num;
1373
+
1374
+ odm_initialize();
1375
+
1376
+ if ((odm_obj = getattr("proc0", "type", 0, &num))) {
1377
+ SIGAR_SSTRCPY(sigar->model, odm_obj->value);
1378
+ free(odm_obj);
1379
+ }
1380
+
1381
+ odm_terminate();
1382
+ }
1383
+
1384
+ return sigar->model;
1385
+ }
1386
+
1387
+ #define SIGAR_CPU_CACHE_SIZE \
1388
+ (_system_configuration.L2_cache_size / 1024)
1389
+
1390
+ static int sigar_get_cpu_mhz(sigar_t *sigar)
1391
+ {
1392
+ if (sigar->cpu_mhz == SIGAR_FIELD_NOTIMPL) {
1393
+ perfstat_cpu_total_t data;
1394
+
1395
+ if (sigar_perfstat_cpu(&data) == 1) {
1396
+ sigar->cpu_mhz = data.processorHZ / 1000000;
1397
+ }
1398
+ else {
1399
+ sigar_log_printf(sigar, SIGAR_LOG_ERROR,
1400
+ "perfstat_cpu_total failed: %s",
1401
+ sigar_strerror(sigar, errno));
1402
+ }
1403
+ }
1404
+
1405
+ return sigar->cpu_mhz;
1406
+ }
1407
+
1408
+ static char *get_cpu_arch(void)
1409
+ {
1410
+ switch (_system_configuration.architecture) {
1411
+ case POWER_RS:
1412
+ return "Power Classic";
1413
+ case POWER_PC:
1414
+ return "PowerPC";
1415
+ case IA64:
1416
+ return "IA64";
1417
+ default:
1418
+ return "PowerPC"; /* what else could it be */
1419
+ }
1420
+ }
1421
+
1422
+ static char *get_ppc_cpu_model(void)
1423
+ {
1424
+ switch (_system_configuration.implementation) {
1425
+ case POWER_RS1:
1426
+ return "RS1";
1427
+ case POWER_RSC:
1428
+ return "RSC";
1429
+ case POWER_RS2:
1430
+ return "RS2";
1431
+ case POWER_601:
1432
+ return "601";
1433
+ case POWER_603:
1434
+ return "603";
1435
+ case POWER_604:
1436
+ return "604";
1437
+ case POWER_620:
1438
+ return "620";
1439
+ case POWER_630:
1440
+ return "630";
1441
+ case POWER_A35:
1442
+ return "A35";
1443
+ case POWER_RS64II:
1444
+ return "RS64-II";
1445
+ case POWER_RS64III:
1446
+ return "RS64-III";
1447
+ case POWER_4:
1448
+ return "POWER4";
1449
+ case POWER_MPC7450:
1450
+ return "MPC7450";
1451
+ case POWER_5:
1452
+ return "POWER5";
1453
+ default:
1454
+ return "Unknown";
1455
+ }
1456
+ }
1457
+
1458
+ static char *get_ia64_cpu_model(void)
1459
+ {
1460
+ switch (_system_configuration.implementation) {
1461
+ case IA64_M1:
1462
+ return "M1";
1463
+ case IA64_M2:
1464
+ return "M2";
1465
+ default:
1466
+ return "Unknown";
1467
+ }
1468
+ }
1469
+
1470
+ static char *get_cpu_model(void)
1471
+ {
1472
+ if (_system_configuration.architecture == IA64) {
1473
+ return get_ia64_cpu_model();
1474
+ }
1475
+ else {
1476
+ return get_ppc_cpu_model();
1477
+ }
1478
+ }
1479
+
1480
+ int sigar_cpu_info_list_get(sigar_t *sigar,
1481
+ sigar_cpu_info_list_t *cpu_infos)
1482
+ {
1483
+ int i;
1484
+ int ncpu = _system_configuration.ncpus; /* this can change */
1485
+ char *arch = get_cpu_arch(), *model = get_cpu_model();
1486
+
1487
+ /*XXX should only do this once*/
1488
+ sigar_cpu_info_list_create(cpu_infos);
1489
+
1490
+ for (i=0; i<ncpu; i++) {
1491
+ sigar_cpu_info_t *info;
1492
+
1493
+ SIGAR_CPU_INFO_LIST_GROW(cpu_infos);
1494
+
1495
+ info = &cpu_infos->data[cpu_infos->number++];
1496
+
1497
+ info->total_cores = ncpu;
1498
+ info->cores_per_socket = 1; /*XXX*/
1499
+ info->total_sockets = ncpu; /*XXX*/
1500
+
1501
+ info->cache_size = SIGAR_CPU_CACHE_SIZE;
1502
+
1503
+ info->mhz = sigar_get_cpu_mhz(sigar);
1504
+
1505
+ if (*arch == 'P') {
1506
+ SIGAR_SSTRCPY(info->vendor, "IBM");
1507
+ }
1508
+ else if (*arch == 'I') {
1509
+ SIGAR_SSTRCPY(info->vendor, "Intel");
1510
+ }
1511
+ else {
1512
+ SIGAR_SSTRCPY(info->vendor, "Unknown");
1513
+ }
1514
+
1515
+ snprintf(info->model, sizeof(info->model),
1516
+ "%s %s", arch, model);
1517
+ }
1518
+
1519
+ return SIGAR_OK;
1520
+ }
1521
+ /* XXX net_route_list copy-n-pasted from darwin_sigar.c; only diff is getkerninfo instead of sysctl */
1522
+ #define rt_s_addr(sa) ((struct sockaddr_in *)(sa))->sin_addr.s_addr
1523
+
1524
+ #ifndef SA_SIZE
1525
+ #define SA_SIZE(sa) \
1526
+ ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \
1527
+ sizeof(long) : \
1528
+ 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
1529
+ #endif
1530
+
1531
+ int sigar_net_route_list_get(sigar_t *sigar,
1532
+ sigar_net_route_list_t *routelist)
1533
+ {
1534
+ int needed;
1535
+ int bit;
1536
+ char *buf, *next, *lim;
1537
+ struct rt_msghdr *rtm;
1538
+
1539
+ needed = getkerninfo(KINFO_RT_DUMP, NULL, NULL, 0);
1540
+ if (needed <= 0) {
1541
+ return errno;
1542
+ }
1543
+
1544
+ buf = malloc(needed);
1545
+
1546
+ if (getkerninfo(KINFO_RT_DUMP, buf, &needed, 0) < 0) {
1547
+ return errno;
1548
+ }
1549
+
1550
+ sigar_net_route_list_create(routelist);
1551
+
1552
+ lim = buf + needed;
1553
+
1554
+ for (next = buf; next < lim; next += rtm->rtm_msglen) {
1555
+ struct sockaddr *sa;
1556
+ sigar_net_route_t *route;
1557
+ rtm = (struct rt_msghdr *)next;
1558
+
1559
+ if (rtm->rtm_type != RTM_GET) {
1560
+ continue;
1561
+ }
1562
+
1563
+ sa = (struct sockaddr *)(rtm + 1);
1564
+
1565
+ if (sa->sa_family != AF_INET) {
1566
+ continue;
1567
+ }
1568
+
1569
+ SIGAR_NET_ROUTE_LIST_GROW(routelist);
1570
+ route = &routelist->data[routelist->number++];
1571
+ SIGAR_ZERO(route);
1572
+
1573
+ route->flags = rtm->rtm_flags;
1574
+ if_indextoname(rtm->rtm_index, route->ifname);
1575
+
1576
+ for (bit=RTA_DST;
1577
+ bit && ((char *)sa < lim);
1578
+ bit <<= 1)
1579
+ {
1580
+ if ((rtm->rtm_addrs & bit) == 0) {
1581
+ continue;
1582
+ }
1583
+ switch (bit) {
1584
+ case RTA_DST:
1585
+ sigar_net_address_set(route->destination,
1586
+ rt_s_addr(sa));
1587
+ break;
1588
+ case RTA_GATEWAY:
1589
+ if (sa->sa_family == AF_INET) {
1590
+ sigar_net_address_set(route->gateway,
1591
+ rt_s_addr(sa));
1592
+ }
1593
+ break;
1594
+ case RTA_NETMASK:
1595
+ sigar_net_address_set(route->mask,
1596
+ rt_s_addr(sa));
1597
+ break;
1598
+ case RTA_IFA:
1599
+ break;
1600
+ }
1601
+
1602
+ sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa));
1603
+ }
1604
+ }
1605
+
1606
+ free(buf);
1607
+
1608
+ return SIGAR_OK;
1609
+ }
1610
+
1611
+ int sigar_net_interface_stat_get(sigar_t *sigar,
1612
+ const char *name,
1613
+ sigar_net_interface_stat_t *ifstat)
1614
+ {
1615
+ perfstat_id_t id;
1616
+ perfstat_netinterface_t data;
1617
+
1618
+ sigar_log(sigar, SIGAR_LOG_DEBUG, "[ifstat] using libperfstat");
1619
+
1620
+ SIGAR_SSTRCPY(id.name, name);
1621
+
1622
+ if (perfstat_netinterface(&id, &data, sizeof(data), 1) == 1) {
1623
+ ifstat->rx_bytes = data.ibytes;
1624
+ ifstat->rx_packets = data.ipackets;
1625
+ ifstat->rx_errors = data.ierrors;
1626
+ ifstat->rx_dropped = SIGAR_FIELD_NOTIMPL;
1627
+ ifstat->rx_overruns = SIGAR_FIELD_NOTIMPL;
1628
+ ifstat->rx_frame = SIGAR_FIELD_NOTIMPL;
1629
+
1630
+ ifstat->tx_bytes = data.obytes;
1631
+ ifstat->tx_packets = data.opackets;
1632
+ ifstat->tx_errors = data.oerrors;
1633
+ ifstat->tx_dropped = SIGAR_FIELD_NOTIMPL;
1634
+ ifstat->tx_overruns = SIGAR_FIELD_NOTIMPL;
1635
+ ifstat->tx_collisions = data.collisions;
1636
+ ifstat->tx_carrier = SIGAR_FIELD_NOTIMPL;
1637
+
1638
+ ifstat->speed = data.bitrate;
1639
+
1640
+ return SIGAR_OK;
1641
+ }
1642
+ else {
1643
+ return errno;
1644
+ }
1645
+ }
1646
+
1647
+ int sigar_net_interface_ipv6_config_get(sigar_t *sigar, const char *name,
1648
+ sigar_net_interface_config_t *ifconfig)
1649
+ {
1650
+ int sock;
1651
+ struct in6_ifreq ifr;
1652
+
1653
+ if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1654
+ return errno;
1655
+ }
1656
+
1657
+ SIGAR_SSTRCPY(ifr.ifr_name, name);
1658
+
1659
+ if (ioctl(sock, SIOCGIFADDR6, &ifr) == 0) {
1660
+ struct in6_addr *addr = SIGAR_SIN6_ADDR(&ifr.ifr_Addr);
1661
+
1662
+ sigar_net_address6_set(ifconfig->address6, addr);
1663
+ sigar_net_interface_scope6_set(ifconfig, addr);
1664
+
1665
+ if (ioctl(sock, SIOCGIFNETMASK6, &ifr) == 0) {
1666
+ addr = SIGAR_SIN6_ADDR(&ifr.ifr_Addr);
1667
+ ifconfig->prefix6_length = SIGAR_SIN6(&ifr.ifr_Addr)->sin6_len; /*XXX*/
1668
+ }
1669
+ }
1670
+
1671
+ close(sock);
1672
+ return SIGAR_OK;
1673
+ }
1674
+
1675
+ #define IS_TCP_SERVER(state, flags) \
1676
+ ((flags & SIGAR_NETCONN_SERVER) && (state == TCPS_LISTEN))
1677
+
1678
+ #define IS_TCP_CLIENT(state, flags) \
1679
+ ((flags & SIGAR_NETCONN_CLIENT) && (state != TCPS_LISTEN))
1680
+
1681
+ static int net_conn_get_tcp(sigar_net_connection_walker_t *walker)
1682
+ {
1683
+ sigar_t *sigar = walker->sigar;
1684
+ int flags = walker->flags;
1685
+ int status;
1686
+ struct inpcb tcp_inpcb;
1687
+ struct tcpcb tcpcb;
1688
+ struct inpcb *entry;
1689
+
1690
+ status = kread(sigar, &tcp_inpcb, sizeof(tcp_inpcb),
1691
+ sigar->koffsets[KOFFSET_TCB]);
1692
+
1693
+ if (status != SIGAR_OK) {
1694
+ return status;
1695
+ }
1696
+
1697
+ entry = tcp_inpcb.inp_next;
1698
+ while (entry) {
1699
+ struct inpcb pcb;
1700
+ int state;
1701
+
1702
+ status = kread(sigar, &pcb, sizeof(pcb), (long)entry);
1703
+ if (status != SIGAR_OK) {
1704
+ return status;
1705
+ }
1706
+ status = kread(sigar, &tcpcb, sizeof(tcpcb), (long)pcb.inp_ppcb);
1707
+ if (status != SIGAR_OK) {
1708
+ return status;
1709
+ }
1710
+
1711
+ state = tcpcb.t_state;
1712
+ if ((IS_TCP_SERVER(state, flags) ||
1713
+ IS_TCP_CLIENT(state, flags)))
1714
+ {
1715
+ sigar_net_connection_t conn;
1716
+
1717
+ SIGAR_ZERO(&conn);
1718
+
1719
+ conn.type = SIGAR_NETCONN_TCP;
1720
+
1721
+ sigar_net_address_set(conn.local_address,
1722
+ pcb.inp_laddr.s_addr);
1723
+
1724
+ sigar_net_address_set(conn.remote_address,
1725
+ pcb.inp_faddr.s_addr);
1726
+
1727
+ conn.local_port = ntohs(pcb.inp_lport);
1728
+ conn.remote_port = ntohs(pcb.inp_fport);
1729
+
1730
+ conn.send_queue = conn.receive_queue = SIGAR_FIELD_NOTIMPL;
1731
+
1732
+ switch (state) {
1733
+ case TCPS_CLOSED:
1734
+ conn.state = SIGAR_TCP_CLOSE;
1735
+ break;
1736
+ case TCPS_LISTEN:
1737
+ conn.state = SIGAR_TCP_LISTEN;
1738
+ break;
1739
+ case TCPS_SYN_SENT:
1740
+ conn.state = SIGAR_TCP_SYN_SENT;
1741
+ break;
1742
+ case TCPS_SYN_RECEIVED:
1743
+ conn.state = SIGAR_TCP_SYN_RECV;
1744
+ break;
1745
+ case TCPS_ESTABLISHED:
1746
+ conn.state = SIGAR_TCP_ESTABLISHED;
1747
+ break;
1748
+ case TCPS_CLOSE_WAIT:
1749
+ conn.state = SIGAR_TCP_CLOSE_WAIT;
1750
+ break;
1751
+ case TCPS_FIN_WAIT_1:
1752
+ conn.state = SIGAR_TCP_FIN_WAIT1;
1753
+ break;
1754
+ case TCPS_CLOSING:
1755
+ conn.state = SIGAR_TCP_CLOSING;
1756
+ break;
1757
+ case TCPS_LAST_ACK:
1758
+ conn.state = SIGAR_TCP_LAST_ACK;
1759
+ break;
1760
+ case TCPS_FIN_WAIT_2:
1761
+ conn.state = SIGAR_TCP_FIN_WAIT2;
1762
+ break;
1763
+ case TCPS_TIME_WAIT:
1764
+ conn.state = SIGAR_TCP_TIME_WAIT;
1765
+ break;
1766
+ default:
1767
+ conn.state = SIGAR_TCP_UNKNOWN;
1768
+ break;
1769
+ }
1770
+
1771
+ if (walker->add_connection(walker, &conn) != SIGAR_OK) {
1772
+ break;
1773
+ }
1774
+ }
1775
+
1776
+ entry = pcb.inp_next;
1777
+ if (entry == tcp_inpcb.inp_next) {
1778
+ break;
1779
+ }
1780
+ }
1781
+
1782
+ return SIGAR_OK;
1783
+ }
1784
+
1785
+ int sigar_net_connection_walk(sigar_net_connection_walker_t *walker)
1786
+ {
1787
+ int status;
1788
+
1789
+ if (walker->flags & SIGAR_NETCONN_TCP) {
1790
+ status = net_conn_get_tcp(walker);
1791
+
1792
+ if (status != SIGAR_OK) {
1793
+ return status;
1794
+ }
1795
+ }
1796
+ #if 0
1797
+ if (walker->flags & SIGAR_NETCONN_UDP) {
1798
+ status = net_conn_get_udp(walker);
1799
+
1800
+ if (status != SIGAR_OK) {
1801
+ return status;
1802
+ }
1803
+ }
1804
+ #endif
1805
+ return SIGAR_OK;
1806
+ }
1807
+
1808
+ SIGAR_DECLARE(int)
1809
+ sigar_tcp_get(sigar_t *sigar,
1810
+ sigar_tcp_t *tcp)
1811
+ {
1812
+ perfstat_id_t id;
1813
+ perfstat_protocol_t proto;
1814
+
1815
+ SIGAR_SSTRCPY(id.name, "tcp");
1816
+
1817
+ if (perfstat_protocol(&id, &proto, sizeof(proto), 1) != 1) {
1818
+ return ENOENT;
1819
+ }
1820
+
1821
+ tcp->active_opens = proto.u.tcp.initiated;
1822
+ tcp->passive_opens = proto.u.tcp.accepted;
1823
+ tcp->attempt_fails = proto.u.tcp.dropped;
1824
+ tcp->estab_resets = proto.u.tcp.dropped;
1825
+ tcp->curr_estab = proto.u.tcp.established;
1826
+ tcp->in_segs = proto.u.tcp.ipackets;
1827
+ tcp->out_segs = proto.u.tcp.opackets;
1828
+ tcp->retrans_segs = 0;
1829
+ tcp->in_errs = proto.u.tcp.ierrors;
1830
+ tcp->out_rsts = 0;
1831
+ }
1832
+
1833
+ #define NFS_V2_STAT_SET(type) \
1834
+ nfs->null = proto.u.nfsv2.type.null; \
1835
+ nfs->getattr = proto.u.nfsv2.type.getattr; \
1836
+ nfs->setattr = proto.u.nfsv2.type.setattr; \
1837
+ nfs->root = proto.u.nfsv2.type.root; \
1838
+ nfs->lookup = proto.u.nfsv2.type.lookup; \
1839
+ nfs->readlink = proto.u.nfsv2.type.readlink; \
1840
+ nfs->read = proto.u.nfsv2.type.read; \
1841
+ nfs->writecache = proto.u.nfsv2.type.writecache; \
1842
+ nfs->write = proto.u.nfsv2.type.write; \
1843
+ nfs->create = proto.u.nfsv2.type.create; \
1844
+ nfs->remove = proto.u.nfsv2.type.remove; \
1845
+ nfs->rename = proto.u.nfsv2.type.rename; \
1846
+ nfs->link = proto.u.nfsv2.type.link; \
1847
+ nfs->symlink = proto.u.nfsv2.type.symlink; \
1848
+ nfs->mkdir = proto.u.nfsv2.type.mkdir; \
1849
+ nfs->rmdir = proto.u.nfsv2.type.rmdir; \
1850
+ nfs->readdir = proto.u.nfsv2.type.readdir; \
1851
+ nfs->fsstat = proto.u.nfsv2.type.statfs
1852
+
1853
+ int sigar_nfs_client_v2_get(sigar_t *sigar,
1854
+ sigar_nfs_client_v2_t *nfs)
1855
+ {
1856
+ perfstat_id_t id;
1857
+ perfstat_protocol_t proto;
1858
+
1859
+ SIGAR_SSTRCPY(id.name, "nfsv2");
1860
+
1861
+ if (perfstat_protocol(&id, &proto, sizeof(proto), 1) != 1) {
1862
+ return ENOENT;
1863
+ }
1864
+
1865
+ NFS_V2_STAT_SET(client);
1866
+
1867
+ return SIGAR_OK;
1868
+ }
1869
+
1870
+ int sigar_nfs_server_v2_get(sigar_t *sigar,
1871
+ sigar_nfs_server_v2_t *nfs)
1872
+ {
1873
+ perfstat_id_t id;
1874
+ perfstat_protocol_t proto;
1875
+
1876
+ SIGAR_SSTRCPY(id.name, "nfsv2");
1877
+
1878
+ if (perfstat_protocol(&id, &proto, sizeof(proto), 1) != 1) {
1879
+ return ENOENT;
1880
+ }
1881
+
1882
+ NFS_V2_STAT_SET(server);
1883
+
1884
+ return SIGAR_OK;
1885
+ }
1886
+
1887
+ #define NFS_V3_STAT_SET(type) \
1888
+ nfs->null = proto.u.nfsv3.type.null; \
1889
+ nfs->getattr = proto.u.nfsv3.type.getattr; \
1890
+ nfs->setattr = proto.u.nfsv3.type.setattr; \
1891
+ nfs->lookup = proto.u.nfsv3.type.lookup; \
1892
+ nfs->access = proto.u.nfsv3.type.access; \
1893
+ nfs->readlink = proto.u.nfsv3.type.readlink; \
1894
+ nfs->read = proto.u.nfsv3.type.read; \
1895
+ nfs->write = proto.u.nfsv3.type.write; \
1896
+ nfs->create = proto.u.nfsv3.type.create; \
1897
+ nfs->mkdir = proto.u.nfsv3.type.mkdir; \
1898
+ nfs->symlink = proto.u.nfsv3.type.symlink; \
1899
+ nfs->mknod = proto.u.nfsv3.type.mknod; \
1900
+ nfs->remove = proto.u.nfsv3.type.remove; \
1901
+ nfs->rmdir = proto.u.nfsv3.type.rmdir; \
1902
+ nfs->rename = proto.u.nfsv3.type.rename; \
1903
+ nfs->link = proto.u.nfsv3.type.link; \
1904
+ nfs->readdir = proto.u.nfsv3.type.readdir; \
1905
+ nfs->readdirplus = proto.u.nfsv3.type.readdirplus; \
1906
+ nfs->fsstat = proto.u.nfsv3.type.fsstat; \
1907
+ nfs->fsinfo = proto.u.nfsv3.type.fsinfo; \
1908
+ nfs->pathconf = proto.u.nfsv3.type.pathconf; \
1909
+ nfs->commit = proto.u.nfsv3.type.commit
1910
+
1911
+ int sigar_nfs_client_v3_get(sigar_t *sigar,
1912
+ sigar_nfs_client_v3_t *nfs)
1913
+ {
1914
+ perfstat_id_t id;
1915
+ perfstat_protocol_t proto;
1916
+
1917
+ SIGAR_SSTRCPY(id.name, "nfsv3");
1918
+
1919
+ if (perfstat_protocol(&id, &proto, sizeof(proto), 1) != 1) {
1920
+ return ENOENT;
1921
+ }
1922
+
1923
+ NFS_V3_STAT_SET(client);
1924
+
1925
+ return SIGAR_OK;
1926
+ }
1927
+
1928
+ int sigar_nfs_server_v3_get(sigar_t *sigar,
1929
+ sigar_nfs_server_v3_t *nfs)
1930
+ {
1931
+ perfstat_id_t id;
1932
+ perfstat_protocol_t proto;
1933
+
1934
+ SIGAR_SSTRCPY(id.name, "nfsv3");
1935
+
1936
+ if (perfstat_protocol(&id, &proto, sizeof(proto), 1) != 1) {
1937
+ return ENOENT;
1938
+ }
1939
+
1940
+ NFS_V3_STAT_SET(server);
1941
+
1942
+ return SIGAR_OK;
1943
+ }
1944
+
1945
+ #include <net/if_arp.h>
1946
+ /*
1947
+ * cannot find any related aix docs on reading the ARP table,
1948
+ * this impl was gleaned from the above .h file and truss -f arp -an
1949
+ */
1950
+ int sigar_arp_list_get(sigar_t *sigar,
1951
+ sigar_arp_list_t *arplist)
1952
+ {
1953
+ int status = SIGAR_OK;
1954
+ long arptabsize;
1955
+ int i, size, retval;
1956
+ struct arptab *arptabp;
1957
+
1958
+ size = sizeof(arptabsize);
1959
+ retval = getkerninfo(KINFO_READ, &arptabsize, &size,
1960
+ sigar->koffsets[KOFFSET_ARPTABSIZE]);
1961
+ if (retval != sizeof(arptabsize)) {
1962
+ return errno;
1963
+ }
1964
+
1965
+ size = sizeof(arptabp);
1966
+ retval = getkerninfo(KINFO_READ, &arptabp, &size,
1967
+ sigar->koffsets[KOFFSET_ARPTABP]);
1968
+ if (retval != sizeof(arptabp)) {
1969
+ return errno;
1970
+ }
1971
+
1972
+ sigar_arp_list_create(arplist);
1973
+ status = SIGAR_OK;
1974
+
1975
+ for (i=0; i<arptabsize; i++) {
1976
+ struct arptab ent;
1977
+ struct ifnet ifp;
1978
+ sigar_arp_t *arp;
1979
+
1980
+ size = sizeof(ent);
1981
+ retval = getkerninfo(KINFO_READ, &ent, &size, arptabp + i);
1982
+ if (retval != sizeof(ent)) {
1983
+ status = errno;
1984
+ break;
1985
+ }
1986
+
1987
+ if (ent.at_flags == 0) {
1988
+ continue; /* empty bucket */
1989
+ }
1990
+
1991
+ size = sizeof(ifp);
1992
+ retval = getkerninfo(KINFO_READ, &ifp, &size, ent.at_ifp);
1993
+ if (retval != sizeof(ifp)) {
1994
+ status = errno;
1995
+ break;
1996
+ }
1997
+
1998
+ SIGAR_ARP_LIST_GROW(arplist);
1999
+ arp = &arplist->data[arplist->number++];
2000
+
2001
+ sigar_net_address_set(arp->address,
2002
+ ent.at_iaddr.s_addr);
2003
+
2004
+ sigar_net_address_mac_set(arp->hwaddr,
2005
+ ent.hwaddr,
2006
+ sizeof(arp->hwaddr.addr.mac));
2007
+
2008
+ if_indextoname(ifp.if_index, arp->ifname);
2009
+
2010
+ arp->flags = ent.at_flags;
2011
+ SIGAR_SSTRCPY(arp->type, "ether"); /* XXX ifp.if_type */
2012
+ }
2013
+
2014
+ if (status != SIGAR_OK) {
2015
+ sigar_arp_list_destroy(sigar, arplist);
2016
+ }
2017
+
2018
+ return status;
2019
+ }
2020
+
2021
+ /* derived from pidentd's k_aix432.c */
2022
+ int sigar_proc_port_get(sigar_t *sigar, int protocol,
2023
+ unsigned long port, sigar_pid_t *pidp)
2024
+ {
2025
+ struct procsinfo pinfo;
2026
+ struct fdsinfo finfo;
2027
+ pid_t pid = 0;
2028
+ int type;
2029
+
2030
+ switch (protocol) {
2031
+ case SIGAR_NETCONN_TCP:
2032
+ type = IPPROTO_TCP;
2033
+ break;
2034
+ case SIGAR_NETCONN_UDP:
2035
+ type = IPPROTO_UDP;
2036
+ break;
2037
+ default:
2038
+ return SIGAR_ENOTIMPL;
2039
+ }
2040
+
2041
+ for (;;) {
2042
+ int fd, status;
2043
+ int num = getprocs(&pinfo, sizeof(pinfo),
2044
+ &finfo, sizeof(finfo),
2045
+ &pid, 1);
2046
+
2047
+ if (num == 0) {
2048
+ break;
2049
+ }
2050
+
2051
+ if ((pinfo.pi_state == 0) || (pinfo.pi_state == SZOMB)) {
2052
+ continue;
2053
+ }
2054
+
2055
+ for (fd = 0; fd < pinfo.pi_maxofile; fd++) {
2056
+ struct file file;
2057
+ struct socket socket, *sockp;
2058
+ struct protosw protosw;
2059
+ struct domain domain;
2060
+ struct inpcb inpcb;
2061
+ long ptr;
2062
+
2063
+ if (!(ptr = (long)finfo.pi_ufd[fd].fp)) {
2064
+ continue;
2065
+ }
2066
+
2067
+ status = kread(sigar, &file, sizeof(file), ptr);
2068
+ if (status != SIGAR_OK) {
2069
+ continue;
2070
+ }
2071
+
2072
+ if (file.f_type != DTYPE_SOCKET) {
2073
+ continue;
2074
+ }
2075
+
2076
+ if (!(sockp = (struct socket *)file.f_data)) {
2077
+ continue;
2078
+ }
2079
+
2080
+ status = kread(sigar, &socket, sizeof(socket), (long)sockp);
2081
+ if (status != SIGAR_OK) {
2082
+ continue;
2083
+ }
2084
+
2085
+ if (!(ptr = (long)socket.so_proto)) {
2086
+ continue;
2087
+ }
2088
+
2089
+ status = kread(sigar, &protosw, sizeof(protosw), ptr);
2090
+ if (status != SIGAR_OK) {
2091
+ continue;
2092
+ }
2093
+
2094
+ if (protosw.pr_protocol != type) {
2095
+ continue;
2096
+ }
2097
+
2098
+ if (!(ptr = (long)protosw.pr_domain)) {
2099
+ continue;
2100
+ }
2101
+
2102
+ status = kread(sigar, &domain, sizeof(domain), ptr);
2103
+ if (status != SIGAR_OK) {
2104
+ continue;
2105
+ }
2106
+
2107
+ if ((domain.dom_family != AF_INET) &&
2108
+ domain.dom_family != AF_INET6)
2109
+ {
2110
+ continue;
2111
+ }
2112
+
2113
+ if (!(ptr = (long)socket.so_pcb)) {
2114
+ continue;
2115
+ }
2116
+
2117
+ status = kread(sigar, &inpcb, sizeof(inpcb), ptr);
2118
+ if (status != SIGAR_OK) {
2119
+ continue;
2120
+ }
2121
+
2122
+ if (sockp != inpcb.inp_socket) {
2123
+ continue;
2124
+ }
2125
+
2126
+ if (inpcb.inp_lport != port) {
2127
+ continue;
2128
+ }
2129
+
2130
+ *pidp = pinfo.pi_pid;
2131
+
2132
+ return SIGAR_OK;
2133
+ }
2134
+ }
2135
+
2136
+ return ENOENT;
2137
+ }
2138
+
2139
+ int sigar_os_sys_info_get(sigar_t *sigar,
2140
+ sigar_sys_info_t *sysinfo)
2141
+ {
2142
+ struct utsname name;
2143
+
2144
+ uname(&name);
2145
+
2146
+ SIGAR_SSTRCPY(sysinfo->vendor, "IBM");
2147
+ SIGAR_SSTRCPY(sysinfo->arch, get_cpu_arch());
2148
+ /* utsname.machine is a sequence number */
2149
+ /* XXX odm might have something better */
2150
+ snprintf(sysinfo->machine,
2151
+ sizeof(sysinfo->machine),
2152
+ "%s %s",
2153
+ sysinfo->arch, get_cpu_model());
2154
+
2155
+ snprintf(sysinfo->version,
2156
+ sizeof(sysinfo->version),
2157
+ "%s.%s",
2158
+ name.version, name.release);
2159
+
2160
+ SIGAR_SSTRCPY(sysinfo->vendor_version, sysinfo->version);
2161
+
2162
+ snprintf(sysinfo->description,
2163
+ sizeof(sysinfo->description),
2164
+ "%s %s",
2165
+ sysinfo->name, sysinfo->version);
2166
+
2167
+ return SIGAR_OK;
2168
+ }