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,53 @@
1
+ /*
2
+ * Copyright (c) 2006-2007 Hyperic, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #ifndef SIGAR_PTQL_H
18
+ #define SIGAR_PTQL_H
19
+
20
+ #define SIGAR_PTQL_MALFORMED_QUERY -1
21
+
22
+ typedef struct sigar_ptql_query_t sigar_ptql_query_t;
23
+
24
+ #define SIGAR_PTQL_ERRMSG_SIZE 1024
25
+
26
+ typedef struct {
27
+ char message[SIGAR_PTQL_ERRMSG_SIZE];
28
+ } sigar_ptql_error_t;
29
+
30
+ typedef int (*sigar_ptql_re_impl_t)(void *, char *, char *);
31
+
32
+ SIGAR_DECLARE(void) sigar_ptql_re_impl_set(sigar_t *sigar, void *data,
33
+ sigar_ptql_re_impl_t impl);
34
+
35
+ SIGAR_DECLARE(int) sigar_ptql_query_create(sigar_ptql_query_t **query,
36
+ char *ptql,
37
+ sigar_ptql_error_t *error);
38
+
39
+ SIGAR_DECLARE(int) sigar_ptql_query_match(sigar_t *sigar,
40
+ sigar_ptql_query_t *query,
41
+ sigar_pid_t pid);
42
+
43
+ SIGAR_DECLARE(int) sigar_ptql_query_destroy(sigar_ptql_query_t *query);
44
+
45
+ SIGAR_DECLARE(int) sigar_ptql_query_find_process(sigar_t *sigar,
46
+ sigar_ptql_query_t *query,
47
+ sigar_pid_t *pid);
48
+
49
+ SIGAR_DECLARE(int) sigar_ptql_query_find(sigar_t *sigar,
50
+ sigar_ptql_query_t *query,
51
+ sigar_proc_list_t *proclist);
52
+
53
+ #endif /*SIGAR_PTQL_H*/
@@ -0,0 +1,191 @@
1
+ /*
2
+ * Copyright (c) 2004-2008 Hyperic, Inc.
3
+ * Copyright (c) 2009 SpringSource, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #ifndef SIGAR_UTIL_H
19
+ #define SIGAR_UTIL_H
20
+
21
+ /* most of this is crap for dealing with linux /proc */
22
+ #define UITOA_BUFFER_SIZE \
23
+ (sizeof(int) * 3 + 1)
24
+
25
+ #define SSTRLEN(s) \
26
+ (sizeof(s)-1)
27
+
28
+ #define sigar_strtoul(ptr) \
29
+ strtoul(ptr, &ptr, 10)
30
+
31
+ #define sigar_strtoull(ptr) \
32
+ strtoull(ptr, &ptr, 10)
33
+
34
+ #define sigar_isspace(c) \
35
+ (isspace(((unsigned char)(c))))
36
+
37
+ #define sigar_isdigit(c) \
38
+ (isdigit(((unsigned char)(c))))
39
+
40
+ #define sigar_isalpha(c) \
41
+ (isalpha(((unsigned char)(c))))
42
+
43
+ #define sigar_isupper(c) \
44
+ (isupper(((unsigned char)(c))))
45
+
46
+ #define sigar_tolower(c) \
47
+ (tolower(((unsigned char)(c))))
48
+
49
+ #ifdef WIN32
50
+ #define sigar_fileno _fileno
51
+ #define sigar_isatty _isatty
52
+ #define sigar_write _write
53
+ #else
54
+ #define sigar_fileno fileno
55
+ #define sigar_isatty isatty
56
+ #define sigar_write write
57
+ #endif
58
+
59
+ #ifndef PROC_FS_ROOT
60
+ #define PROC_FS_ROOT "/proc/"
61
+ #endif
62
+
63
+ #ifndef PROCP_FS_ROOT
64
+ #define PROCP_FS_ROOT "/proc/"
65
+ #endif
66
+
67
+ sigar_int64_t sigar_time_now_millis(void);
68
+
69
+ char *sigar_uitoa(char *buf, unsigned int n, int *len);
70
+
71
+ int sigar_inet_ntoa(sigar_t *sigar,
72
+ sigar_uint32_t address,
73
+ char *addr_str);
74
+
75
+ struct hostent *sigar_gethostbyname(const char *name,
76
+ sigar_hostent_t *data);
77
+
78
+ SIGAR_INLINE char *sigar_skip_line(char *buffer, int buflen);
79
+
80
+ SIGAR_INLINE char *sigar_skip_token(char *p);
81
+
82
+ SIGAR_INLINE char *sigar_skip_multiple_token(char *p, int count);
83
+
84
+ char *sigar_getword(char **line, char stop);
85
+
86
+ char *sigar_strcasestr(const char *s1, const char *s2);
87
+
88
+ int sigar_file2str(const char *fname, char *buffer, int buflen);
89
+
90
+ int sigar_proc_file2str(char *buffer, int buflen,
91
+ sigar_pid_t pid,
92
+ const char *fname,
93
+ int fname_len);
94
+
95
+ #define SIGAR_PROC_FILE2STR(buffer, pid, fname) \
96
+ sigar_proc_file2str(buffer, sizeof(buffer), \
97
+ pid, fname, SSTRLEN(fname))
98
+
99
+ #define SIGAR_PROC_FILENAME(buffer, pid, fname) \
100
+ sigar_proc_filename(buffer, sizeof(buffer), \
101
+ pid, fname, SSTRLEN(fname))
102
+
103
+ #define SIGAR_SKIP_SPACE(ptr) \
104
+ while (sigar_isspace(*ptr)) ++ptr
105
+
106
+ char *sigar_proc_filename(char *buffer, int buflen,
107
+ sigar_pid_t pid,
108
+ const char *fname, int fname_len);
109
+
110
+ int sigar_proc_list_procfs_get(sigar_t *sigar,
111
+ sigar_proc_list_t *proclist);
112
+
113
+ int sigar_proc_fd_count(sigar_t *sigar, sigar_pid_t pid,
114
+ sigar_uint64_t *total);
115
+
116
+ /* linux + freebsd */
117
+ int sigar_procfs_args_get(sigar_t *sigar, sigar_pid_t pid,
118
+ sigar_proc_args_t *procargs);
119
+
120
+ int sigar_mem_calc_ram(sigar_t *sigar, sigar_mem_t *mem);
121
+
122
+ int sigar_statvfs(sigar_t *sigar,
123
+ const char *dirname,
124
+ sigar_file_system_usage_t *fsusage);
125
+
126
+ double sigar_file_system_usage_calc_used(sigar_t *sigar,
127
+ sigar_file_system_usage_t *fs);
128
+
129
+ #define SIGAR_DEV_PREFIX "/dev/"
130
+
131
+ #define SIGAR_NAME_IS_DEV(dev) \
132
+ strnEQ(dev, SIGAR_DEV_PREFIX, SSTRLEN(SIGAR_DEV_PREFIX))
133
+
134
+ typedef struct {
135
+ char name[256];
136
+ int is_partition;
137
+ sigar_disk_usage_t disk;
138
+ } sigar_iodev_t;
139
+
140
+ sigar_iodev_t *sigar_iodev_get(sigar_t *sigar,
141
+ const char *dirname);
142
+
143
+ int sigar_cpu_core_count(sigar_t *sigar);
144
+
145
+ /* e.g. VM guest may have 1 virtual ncpu on multicore hosts */
146
+ #define sigar_cpu_socket_count(sigar) \
147
+ (sigar->ncpu < sigar->lcpu) ? sigar->ncpu : \
148
+ (sigar->ncpu / sigar->lcpu)
149
+
150
+ int sigar_cpu_core_rollup(sigar_t *sigar);
151
+
152
+ void sigar_cpu_model_adjust(sigar_t *sigar, sigar_cpu_info_t *info);
153
+
154
+ int sigar_cpu_mhz_from_model(char *model);
155
+
156
+ char *sigar_get_self_path(sigar_t *sigar);
157
+
158
+ #if defined(__sun) || defined(__FreeBSD__)
159
+
160
+ #define SIGAR_HAS_DLINFO_MODULES
161
+ #include <dlfcn.h>
162
+ #include <link.h>
163
+
164
+ int sigar_dlinfo_modules(sigar_t *sigar, sigar_proc_modules_t *procmods);
165
+ #endif
166
+
167
+ typedef struct sigar_cache_entry_t sigar_cache_entry_t;
168
+
169
+ struct sigar_cache_entry_t {
170
+ sigar_cache_entry_t *next;
171
+ sigar_uint64_t id;
172
+ void *value;
173
+ };
174
+
175
+ typedef struct {
176
+ sigar_cache_entry_t **entries;
177
+ unsigned int count, size;
178
+ void (*free_value)(void *ptr);
179
+ } sigar_cache_t;
180
+
181
+ sigar_cache_t *sigar_cache_new(int size);
182
+
183
+ sigar_cache_entry_t *sigar_cache_get(sigar_cache_t *table,
184
+ sigar_uint64_t key);
185
+
186
+ sigar_cache_entry_t *sigar_cache_find(sigar_cache_t *table,
187
+ sigar_uint64_t key);
188
+
189
+ void sigar_cache_destroy(sigar_cache_t *table);
190
+
191
+ #endif /* SIGAR_UTIL_H */
@@ -0,0 +1,2151 @@
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_cred_get(sigar_t *sigar, sigar_pid_t pid,
758
+ sigar_proc_cred_t *proccred)
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
+
767
+ proccred->uid = pinfo->pi_cred.cr_ruid;
768
+ proccred->euid = pinfo->pi_cred.cr_uid;
769
+ if (proccred->uid == -1) {
770
+ /*
771
+ * aix 5.2 has a process named 'jfsz'
772
+ * where uid is '-1', getpwuid returns EPERM
773
+ */
774
+ proccred->uid = proccred->euid = 0;
775
+ }
776
+ proccred->gid = pinfo->pi_cred.cr_rgid;
777
+ proccred->egid = pinfo->pi_cred.cr_gid;
778
+
779
+ return SIGAR_OK;
780
+ }
781
+
782
+ int sigar_proc_time_get(sigar_t *sigar, sigar_pid_t pid,
783
+ sigar_proc_time_t *proctime)
784
+ {
785
+ int status = sigar_getprocs(sigar, pid);
786
+ struct procsinfo64 *pinfo = sigar->pinfo;
787
+
788
+ if (status != SIGAR_OK) {
789
+ return status;
790
+ }
791
+
792
+ proctime->start_time = pinfo->pi_start;
793
+ proctime->start_time *= SIGAR_MSEC; /* convert to ms */
794
+ proctime->user = pinfo->pi_utime * SIGAR_MSEC;
795
+ proctime->sys = pinfo->pi_stime * SIGAR_MSEC;
796
+ proctime->total = proctime->user + proctime->sys;
797
+
798
+ return SIGAR_OK;
799
+ }
800
+
801
+ int sigar_proc_state_get(sigar_t *sigar, sigar_pid_t pid,
802
+ sigar_proc_state_t *procstate)
803
+ {
804
+ int status = sigar_getprocs(sigar, pid);
805
+ struct procsinfo64 *pinfo = sigar->pinfo;
806
+ tid_t tid = 0;
807
+ struct thrdsinfo64 thrinfo;
808
+
809
+ if (status != SIGAR_OK) {
810
+ return status;
811
+ }
812
+
813
+ if (getthrds(pid, &thrinfo, sizeof(thrinfo), &tid, 1) == 1) {
814
+ procstate->processor = thrinfo.ti_affinity;
815
+ }
816
+ else {
817
+ procstate->processor = SIGAR_FIELD_NOTIMPL;
818
+ }
819
+
820
+ SIGAR_SSTRCPY(procstate->name, pinfo->pi_comm);
821
+ procstate->ppid = pinfo->pi_ppid;
822
+ procstate->nice = pinfo->pi_nice;
823
+ procstate->tty = pinfo->pi_ttyd;
824
+ procstate->priority = pinfo->pi_pri;
825
+ procstate->threads = pinfo->pi_thcount;
826
+
827
+ switch (pinfo->pi_state) {
828
+ case SACTIVE:
829
+ procstate->state = 'R';
830
+ break;
831
+ case SIDL:
832
+ procstate->state = 'D';
833
+ break;
834
+ case SSTOP:
835
+ procstate->state = 'S';
836
+ break;
837
+ case SZOMB:
838
+ procstate->state = 'Z';
839
+ break;
840
+ case SSWAP:
841
+ procstate->state = 'S';
842
+ break;
843
+ }
844
+
845
+ return SIGAR_OK;
846
+ }
847
+
848
+ int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid,
849
+ sigar_proc_args_t *procargs)
850
+ {
851
+ /* XXX if buffer is not large enough args are truncated */
852
+ char buffer[8192], *ptr;
853
+ struct procsinfo pinfo;
854
+
855
+ pinfo.pi_pid = pid;
856
+
857
+ if (getargs(&pinfo, sizeof(pinfo),
858
+ buffer, sizeof(buffer)) != 0)
859
+ {
860
+ return errno;
861
+ }
862
+
863
+ ptr = buffer;
864
+
865
+ while (*ptr) {
866
+ int alen = strlen(ptr)+1;
867
+ char *arg = malloc(alen);
868
+
869
+ SIGAR_PROC_ARGS_GROW(procargs);
870
+ memcpy(arg, ptr, alen);
871
+
872
+ procargs->data[procargs->number++] = arg;
873
+
874
+ ptr += alen;
875
+ }
876
+
877
+ return SIGAR_OK;
878
+ }
879
+
880
+ int sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid,
881
+ sigar_proc_env_t *procenv)
882
+ {
883
+ /* XXX if buffer is not large enough args are truncated */
884
+ char buffer[8192], *ptr;
885
+ struct procsinfo pinfo;
886
+
887
+ pinfo.pi_pid = pid;
888
+
889
+ if (getevars(&pinfo, sizeof(pinfo),
890
+ buffer, sizeof(buffer)) != 0)
891
+ {
892
+ return errno;
893
+ }
894
+
895
+ ptr = buffer;
896
+
897
+ while (*ptr) {
898
+ char *val = strchr(ptr, '=');
899
+ int klen, vlen, status;
900
+ char key[128]; /* XXX is there a max key size? */
901
+
902
+ if (val == NULL) {
903
+ /* not key=val format */
904
+ procenv->env_getter(procenv->data, ptr, strlen(ptr), NULL, 0);
905
+ break;
906
+ }
907
+
908
+ klen = val - ptr;
909
+ SIGAR_SSTRCPY(key, ptr);
910
+ key[klen] = '\0';
911
+ ++val;
912
+
913
+ vlen = strlen(val);
914
+ status = procenv->env_getter(procenv->data,
915
+ key, klen, val, vlen);
916
+
917
+ if (status != SIGAR_OK) {
918
+ /* not an error; just stop iterating */
919
+ break;
920
+ }
921
+
922
+ ptr += (klen + 1 + vlen + 1);
923
+ }
924
+
925
+ return SIGAR_OK;
926
+ }
927
+
928
+ int sigar_proc_fd_get(sigar_t *sigar, sigar_pid_t pid,
929
+ sigar_proc_fd_t *procfd)
930
+ {
931
+ #ifdef SIGAR_64BIT
932
+ /* XXX no getuser() in 64-bit mode */
933
+ return SIGAR_ENOTIMPL;
934
+ #else
935
+ int i;
936
+ struct procsinfo pinfo;
937
+ struct user uinfo;
938
+
939
+ procfd->total = 0;
940
+ pinfo.pi_pid = pid;
941
+
942
+ if (getuser(&pinfo, sizeof(pinfo),
943
+ &uinfo, sizeof(uinfo)) != 0) {
944
+ if (errno == EINVAL) {
945
+ return SIGAR_ENOTIMPL; /*XXX 5.2+*/
946
+ }
947
+ }
948
+
949
+ /* see sys/user.h */
950
+ for (i=0; i<uinfo.U_maxofile; i++) {
951
+ if (uinfo.U_ofile(i)) {
952
+ procfd->total++;
953
+ }
954
+ }
955
+
956
+ return SIGAR_OK;
957
+ #endif
958
+ }
959
+
960
+ int sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid,
961
+ sigar_proc_exe_t *procexe)
962
+ {
963
+ int len;
964
+ char buffer[8192];
965
+ struct procsinfo pinfo;
966
+
967
+ pinfo.pi_pid = pid;
968
+
969
+ if (getargs(&pinfo, sizeof(pinfo),
970
+ buffer, sizeof(buffer)) != 0)
971
+ {
972
+ return errno;
973
+ }
974
+ /* XXX argv[0] might be relative */
975
+ len = strlen(buffer);
976
+ SIGAR_SSTRCPY(procexe->name, buffer);
977
+
978
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/cwd");
979
+
980
+ if ((len = readlink(buffer, procexe->cwd,
981
+ sizeof(procexe->cwd)-1)) < 0)
982
+ {
983
+ return errno;
984
+ }
985
+ procexe->cwd[len] = '\0';
986
+
987
+ procexe->root[0] = '\0';
988
+
989
+ return SIGAR_OK;
990
+ }
991
+
992
+ static int sigar_proc_modules_local_get(sigar_t *sigar,
993
+ sigar_proc_modules_t *procmods)
994
+ {
995
+ struct ld_info *info;
996
+ char *buffer;
997
+ int size = 2048, status;
998
+ unsigned int offset;
999
+
1000
+ buffer = malloc(size);
1001
+ while ((loadquery(L_GETINFO, buffer, size) == -1) &&
1002
+ (errno == ENOMEM))
1003
+ {
1004
+ size += 2048;
1005
+ buffer = realloc(buffer, size);
1006
+ }
1007
+
1008
+ info = (struct ld_info *)buffer;
1009
+
1010
+ do {
1011
+ char *name = info->ldinfo_filename;
1012
+
1013
+ status =
1014
+ procmods->module_getter(procmods->data, name, strlen(name));
1015
+
1016
+ if (status != SIGAR_OK) {
1017
+ /* not an error; just stop iterating */
1018
+ free(buffer);
1019
+ return status;
1020
+ }
1021
+
1022
+ offset = info->ldinfo_next;
1023
+ info = (struct ld_info *)((char*)info + offset);
1024
+ } while(offset);
1025
+
1026
+ free(buffer);
1027
+
1028
+ return SIGAR_OK;
1029
+ }
1030
+
1031
+ int sigar_proc_modules_get(sigar_t *sigar, sigar_pid_t pid,
1032
+ sigar_proc_modules_t *procmods)
1033
+ {
1034
+ if (pid == sigar_pid_get(sigar)) {
1035
+ return sigar_proc_modules_local_get(sigar, procmods);
1036
+ }
1037
+ else {
1038
+ return SIGAR_ENOTIMPL;
1039
+ }
1040
+ }
1041
+
1042
+ #define SIGAR_MICROSEC2NANO(s) \
1043
+ ((sigar_uint64_t)(s) * (sigar_uint64_t)1000)
1044
+
1045
+ #define TIME_NSEC(t) \
1046
+ (SIGAR_SEC2NANO((t).tv_sec) + SIGAR_MICROSEC2NANO((t).tv_usec))
1047
+
1048
+ int sigar_thread_cpu_get(sigar_t *sigar,
1049
+ sigar_uint64_t id,
1050
+ sigar_thread_cpu_t *cpu)
1051
+ {
1052
+ struct rusage usage;
1053
+ int retval;
1054
+
1055
+ if (sigar->thrusage != PTHRDSINFO_RUSAGE_START) {
1056
+ sigar->thrusage = PTHRDSINFO_RUSAGE_START;
1057
+ retval =
1058
+ sigar_thread_rusage(&usage,
1059
+ PTHRDSINFO_RUSAGE_START);
1060
+ if (retval != 0) {
1061
+ return retval;
1062
+ }
1063
+ }
1064
+
1065
+ retval =
1066
+ sigar_thread_rusage(&usage,
1067
+ PTHRDSINFO_RUSAGE_COLLECT);
1068
+ if (retval != 0) {
1069
+ return retval;
1070
+ }
1071
+
1072
+ cpu->user = TIME_NSEC(usage.ru_utime);
1073
+ cpu->sys = TIME_NSEC(usage.ru_stime);
1074
+ cpu->total = TIME_NSEC(usage.ru_utime) + TIME_NSEC(usage.ru_stime);
1075
+
1076
+ return SIGAR_OK;
1077
+ }
1078
+
1079
+ int sigar_os_fs_type_get(sigar_file_system_t *fsp)
1080
+ {
1081
+ return fsp->type;
1082
+ }
1083
+
1084
+ #ifndef MNT_NFS4
1085
+ /* another one documented in aix tech ref
1086
+ * with no friggin prototype in any header file...
1087
+ * ...but added in 5.2
1088
+ */
1089
+ int mntctl(int command, int size, char *buffer);
1090
+ #endif
1091
+
1092
+ int sigar_file_system_list_get(sigar_t *sigar,
1093
+ sigar_file_system_list_t *fslist)
1094
+ {
1095
+ int i, size, num;
1096
+ char *buf, *mntlist;
1097
+
1098
+ /* get required size */
1099
+ if (mntctl(MCTL_QUERY, sizeof(size), (char *)&size) < 0) {
1100
+ return errno;
1101
+ }
1102
+
1103
+ mntlist = buf = malloc(size);
1104
+
1105
+ if ((num = mntctl(MCTL_QUERY, size, buf)) < 0) {
1106
+ free(buf);
1107
+ return errno;
1108
+ }
1109
+
1110
+ sigar_file_system_list_create(fslist);
1111
+
1112
+ for (i=0; i<num; i++) {
1113
+ char *devname;
1114
+ const char *typename = NULL;
1115
+ sigar_file_system_t *fsp;
1116
+ struct vmount *ent = (struct vmount *)mntlist;
1117
+
1118
+ mntlist += ent->vmt_length;
1119
+
1120
+ SIGAR_FILE_SYSTEM_LIST_GROW(fslist);
1121
+
1122
+ fsp = &fslist->data[fslist->number++];
1123
+
1124
+ switch (ent->vmt_gfstype) {
1125
+ case MNT_AIX:
1126
+ typename = "aix";
1127
+ fsp->type = SIGAR_FSTYPE_LOCAL_DISK;
1128
+ break;
1129
+ case MNT_JFS:
1130
+ typename = "jfs";
1131
+ fsp->type = SIGAR_FSTYPE_LOCAL_DISK;
1132
+ break;
1133
+ case MNT_NFS:
1134
+ case MNT_NFS3:
1135
+ typename = "nfs";
1136
+ fsp->type = SIGAR_FSTYPE_NETWORK;
1137
+ break;
1138
+ case MNT_CDROM:
1139
+ fsp->type = SIGAR_FSTYPE_CDROM;
1140
+ break;
1141
+ case MNT_SFS:
1142
+ case MNT_CACHEFS:
1143
+ case MNT_AUTOFS:
1144
+ default:
1145
+ if (ent->vmt_flags & MNT_REMOTE) {
1146
+ fsp->type = SIGAR_FSTYPE_NETWORK;
1147
+ }
1148
+ else {
1149
+ fsp->type = SIGAR_FSTYPE_NONE;
1150
+ }
1151
+ }
1152
+
1153
+ SIGAR_SSTRCPY(fsp->dir_name, vmt2dataptr(ent, VMT_STUB));
1154
+ SIGAR_SSTRCPY(fsp->options, vmt2dataptr(ent, VMT_ARGS));
1155
+
1156
+ devname = vmt2dataptr(ent, VMT_OBJECT);
1157
+
1158
+ if (fsp->type == SIGAR_FSTYPE_NETWORK) {
1159
+ char *hostname = vmt2dataptr(ent, VMT_HOSTNAME);
1160
+ #if 0
1161
+ /* XXX: these do not seem reliable */
1162
+ int hostname_len = vmt2datasize(ent, VMT_HOSTNAME)-1; /* -1 == skip '\0' */
1163
+ int devname_len = vmt2datasize(ent, VMT_OBJECT); /* includes '\0' */
1164
+ #else
1165
+ int hostname_len = strlen(hostname);
1166
+ int devname_len = strlen(devname) + 1;
1167
+ #endif
1168
+ int total_len = hostname_len + devname_len + 1; /* 1 == strlen(":") */
1169
+
1170
+ if (total_len > sizeof(fsp->dev_name)) {
1171
+ /* justincase - prevent overflow. chances: slim..none */
1172
+ SIGAR_SSTRCPY(fsp->dev_name, devname);
1173
+ }
1174
+ else {
1175
+ /* sprintf(fsp->devname, "%s:%s", hostname, devname) */
1176
+ char *ptr = fsp->dev_name;
1177
+
1178
+ memcpy(ptr, hostname, hostname_len);
1179
+ ptr += hostname_len;
1180
+
1181
+ *ptr++ = ':';
1182
+
1183
+ memcpy(ptr, devname, devname_len);
1184
+ }
1185
+ }
1186
+ else {
1187
+ SIGAR_SSTRCPY(fsp->dev_name, devname);
1188
+ }
1189
+
1190
+ /* we set fsp->type, just looking up sigar.c:fstype_names[type] */
1191
+ sigar_fs_type_get(fsp);
1192
+
1193
+ if (typename == NULL) {
1194
+ typename = fsp->type_name;
1195
+ }
1196
+
1197
+ SIGAR_SSTRCPY(fsp->sys_type_name, typename);
1198
+ }
1199
+
1200
+ free(buf);
1201
+
1202
+ return SIGAR_OK;
1203
+ }
1204
+
1205
+ typedef struct {
1206
+ char name[IDENTIFIER_LENGTH];
1207
+ long addr;
1208
+ } aix_diskio_t;
1209
+
1210
+ static int create_diskmap(sigar_t *sigar)
1211
+ {
1212
+ int i, total, num;
1213
+ perfstat_disk_t *disk;
1214
+ perfstat_id_t id;
1215
+
1216
+ total = perfstat_disk(NULL, NULL, sizeof(*disk), 0);
1217
+ if (total < 1) {
1218
+ return ENOENT;
1219
+ }
1220
+
1221
+ disk = malloc(total * sizeof(*disk));
1222
+ id.name[0] = '\0';
1223
+
1224
+ num = perfstat_disk(&id, disk, sizeof(*disk), total);
1225
+ if (num < 1) {
1226
+ free(disk);
1227
+ return ENOENT;
1228
+ }
1229
+
1230
+ sigar->diskmap = sigar_cache_new(25);
1231
+
1232
+ odm_initialize();
1233
+
1234
+ for (i=0; i<num; i++) {
1235
+ char query[256];
1236
+ struct CuDv *dv, *ptr;
1237
+ struct listinfo info;
1238
+ sigar_cache_entry_t *ent;
1239
+ int j;
1240
+
1241
+ snprintf(query, sizeof(query),
1242
+ "parent = '%s'", disk[i].vgname);
1243
+
1244
+ ptr = dv = odm_get_list(CuDv_CLASS, query, &info, 256, 1);
1245
+ if ((int)dv == -1) {
1246
+ continue; /* XXX */
1247
+ }
1248
+
1249
+ for (j=0; j<info.num; j++, ptr++) {
1250
+ struct CuAt *attr;
1251
+ int num, retval;
1252
+ struct stat sb;
1253
+
1254
+ if ((attr = getattr(ptr->name, "label", 0, &num))) {
1255
+ retval = stat(attr->value, &sb);
1256
+
1257
+ if (retval == 0) {
1258
+ aix_diskio_t *diskio = malloc(sizeof(*diskio));
1259
+ SIGAR_SSTRCPY(diskio->name, disk[i].name);
1260
+ diskio->addr = -1;
1261
+ ent = sigar_cache_get(sigar->diskmap, SIGAR_FSDEV_ID(sb));
1262
+ ent->value = diskio;
1263
+ }
1264
+
1265
+ free(attr);
1266
+ }
1267
+ }
1268
+
1269
+ odm_free_list(dv, &info);
1270
+ }
1271
+
1272
+ free(disk);
1273
+ odm_terminate();
1274
+
1275
+ return SIGAR_OK;
1276
+ }
1277
+
1278
+ int sigar_disk_usage_get(sigar_t *sigar, const char *name,
1279
+ sigar_disk_usage_t *usage)
1280
+ {
1281
+ perfstat_disk_t disk;
1282
+ perfstat_id_t id;
1283
+
1284
+ SIGAR_SSTRCPY(id.name, name);
1285
+
1286
+ if (perfstat_disk(&id, &disk, sizeof(disk), 1) != 1) {
1287
+ return ENXIO;
1288
+ }
1289
+
1290
+ usage->reads = disk.rblks;
1291
+ usage->writes = disk.wblks;
1292
+ usage->read_bytes = disk.rblks * disk.bsize;
1293
+ usage->write_bytes = disk.wblks * disk.bsize;
1294
+ usage->queue = disk.qdepth;
1295
+ usage->time = disk.time;
1296
+ usage->rtime = SIGAR_FIELD_NOTIMPL;
1297
+ usage->wtime = SIGAR_FIELD_NOTIMPL;
1298
+
1299
+ return SIGAR_OK;
1300
+ }
1301
+
1302
+ int sigar_file_system_usage_get(sigar_t *sigar,
1303
+ const char *dirname,
1304
+ sigar_file_system_usage_t *fsusage)
1305
+ {
1306
+ sigar_cache_entry_t *ent;
1307
+ struct stat sb;
1308
+ int status;
1309
+
1310
+ status = sigar_statvfs(sigar, dirname, fsusage);
1311
+
1312
+ if (status != SIGAR_OK) {
1313
+ return status;
1314
+ }
1315
+
1316
+ fsusage->use_percent = sigar_file_system_usage_calc_used(sigar, fsusage);
1317
+
1318
+ SIGAR_DISK_STATS_INIT(&fsusage->disk);
1319
+
1320
+ if (!sigar->diskmap) {
1321
+ status = create_diskmap(sigar);
1322
+ if (status != SIGAR_OK) {
1323
+ return SIGAR_OK;
1324
+ }
1325
+ }
1326
+
1327
+ status = stat(dirname, &sb);
1328
+ if (status == 0) {
1329
+ sigar_cache_entry_t *ent =
1330
+ sigar_cache_get(sigar->diskmap, SIGAR_FSDEV_ID(sb));
1331
+ if (!ent->value) {
1332
+ return SIGAR_OK;
1333
+ }
1334
+ sigar_disk_usage_get(sigar, ((aix_diskio_t *)ent->value)->name, &fsusage->disk);
1335
+ }
1336
+
1337
+ return SIGAR_OK;
1338
+ }
1339
+
1340
+ /* from sys/systemcfg.h, not defined in 4.3 headers */
1341
+ #ifndef POWER_4
1342
+ #define POWER_4 0x0800
1343
+ #endif
1344
+ #ifndef POWER_MPC7450
1345
+ #define POWER_MPC7450 0x1000
1346
+ #endif
1347
+ #ifndef POWER_5
1348
+ #define POWER_5 0x2000
1349
+ #endif
1350
+
1351
+ static char *sigar_get_odm_model(sigar_t *sigar)
1352
+ {
1353
+ if (sigar->model[0] == '\0') {
1354
+ struct CuAt *odm_obj;
1355
+ int num;
1356
+
1357
+ odm_initialize();
1358
+
1359
+ if ((odm_obj = getattr("proc0", "type", 0, &num))) {
1360
+ SIGAR_SSTRCPY(sigar->model, odm_obj->value);
1361
+ free(odm_obj);
1362
+ }
1363
+
1364
+ odm_terminate();
1365
+ }
1366
+
1367
+ return sigar->model;
1368
+ }
1369
+
1370
+ #define SIGAR_CPU_CACHE_SIZE \
1371
+ (_system_configuration.L2_cache_size / 1024)
1372
+
1373
+ static int sigar_get_cpu_mhz(sigar_t *sigar)
1374
+ {
1375
+ if (sigar->cpu_mhz == SIGAR_FIELD_NOTIMPL) {
1376
+ perfstat_cpu_total_t data;
1377
+
1378
+ if (sigar_perfstat_cpu(&data) == 1) {
1379
+ sigar->cpu_mhz = data.processorHZ / 1000000;
1380
+ }
1381
+ else {
1382
+ sigar_log_printf(sigar, SIGAR_LOG_ERROR,
1383
+ "perfstat_cpu_total failed: %s",
1384
+ sigar_strerror(sigar, errno));
1385
+ }
1386
+ }
1387
+
1388
+ return sigar->cpu_mhz;
1389
+ }
1390
+
1391
+ static char *get_cpu_arch(void)
1392
+ {
1393
+ switch (_system_configuration.architecture) {
1394
+ case POWER_RS:
1395
+ return "Power Classic";
1396
+ case POWER_PC:
1397
+ return "PowerPC";
1398
+ case IA64:
1399
+ return "IA64";
1400
+ default:
1401
+ return "PowerPC"; /* what else could it be */
1402
+ }
1403
+ }
1404
+
1405
+ static char *get_ppc_cpu_model(void)
1406
+ {
1407
+ switch (_system_configuration.implementation) {
1408
+ case POWER_RS1:
1409
+ return "RS1";
1410
+ case POWER_RSC:
1411
+ return "RSC";
1412
+ case POWER_RS2:
1413
+ return "RS2";
1414
+ case POWER_601:
1415
+ return "601";
1416
+ case POWER_603:
1417
+ return "603";
1418
+ case POWER_604:
1419
+ return "604";
1420
+ case POWER_620:
1421
+ return "620";
1422
+ case POWER_630:
1423
+ return "630";
1424
+ case POWER_A35:
1425
+ return "A35";
1426
+ case POWER_RS64II:
1427
+ return "RS64-II";
1428
+ case POWER_RS64III:
1429
+ return "RS64-III";
1430
+ case POWER_4:
1431
+ return "POWER4";
1432
+ case POWER_MPC7450:
1433
+ return "MPC7450";
1434
+ case POWER_5:
1435
+ return "POWER5";
1436
+ default:
1437
+ return "Unknown";
1438
+ }
1439
+ }
1440
+
1441
+ static char *get_ia64_cpu_model(void)
1442
+ {
1443
+ switch (_system_configuration.implementation) {
1444
+ case IA64_M1:
1445
+ return "M1";
1446
+ case IA64_M2:
1447
+ return "M2";
1448
+ default:
1449
+ return "Unknown";
1450
+ }
1451
+ }
1452
+
1453
+ static char *get_cpu_model(void)
1454
+ {
1455
+ if (_system_configuration.architecture == IA64) {
1456
+ return get_ia64_cpu_model();
1457
+ }
1458
+ else {
1459
+ return get_ppc_cpu_model();
1460
+ }
1461
+ }
1462
+
1463
+ int sigar_cpu_info_list_get(sigar_t *sigar,
1464
+ sigar_cpu_info_list_t *cpu_infos)
1465
+ {
1466
+ int i;
1467
+ int ncpu = _system_configuration.ncpus; /* this can change */
1468
+ char *arch = get_cpu_arch(), *model = get_cpu_model();
1469
+
1470
+ /*XXX should only do this once*/
1471
+ sigar_cpu_info_list_create(cpu_infos);
1472
+
1473
+ for (i=0; i<ncpu; i++) {
1474
+ sigar_cpu_info_t *info;
1475
+
1476
+ SIGAR_CPU_INFO_LIST_GROW(cpu_infos);
1477
+
1478
+ info = &cpu_infos->data[cpu_infos->number++];
1479
+
1480
+ info->total_cores = ncpu;
1481
+ info->cores_per_socket = 1; /*XXX*/
1482
+ info->total_sockets = ncpu; /*XXX*/
1483
+
1484
+ info->cache_size = SIGAR_CPU_CACHE_SIZE;
1485
+
1486
+ info->mhz = sigar_get_cpu_mhz(sigar);
1487
+
1488
+ if (*arch == 'P') {
1489
+ SIGAR_SSTRCPY(info->vendor, "IBM");
1490
+ }
1491
+ else if (*arch == 'I') {
1492
+ SIGAR_SSTRCPY(info->vendor, "Intel");
1493
+ }
1494
+ else {
1495
+ SIGAR_SSTRCPY(info->vendor, "Unknown");
1496
+ }
1497
+
1498
+ snprintf(info->model, sizeof(info->model),
1499
+ "%s %s", arch, model);
1500
+ }
1501
+
1502
+ return SIGAR_OK;
1503
+ }
1504
+ /* XXX net_route_list copy-n-pasted from darwin_sigar.c; only diff is getkerninfo instead of sysctl */
1505
+ #define rt_s_addr(sa) ((struct sockaddr_in *)(sa))->sin_addr.s_addr
1506
+
1507
+ #ifndef SA_SIZE
1508
+ #define SA_SIZE(sa) \
1509
+ ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \
1510
+ sizeof(long) : \
1511
+ 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
1512
+ #endif
1513
+
1514
+ int sigar_net_route_list_get(sigar_t *sigar,
1515
+ sigar_net_route_list_t *routelist)
1516
+ {
1517
+ int needed;
1518
+ int bit;
1519
+ char *buf, *next, *lim;
1520
+ struct rt_msghdr *rtm;
1521
+
1522
+ needed = getkerninfo(KINFO_RT_DUMP, NULL, NULL, 0);
1523
+ if (needed <= 0) {
1524
+ return errno;
1525
+ }
1526
+
1527
+ buf = malloc(needed);
1528
+
1529
+ if (getkerninfo(KINFO_RT_DUMP, buf, &needed, 0) < 0) {
1530
+ return errno;
1531
+ }
1532
+
1533
+ sigar_net_route_list_create(routelist);
1534
+
1535
+ lim = buf + needed;
1536
+
1537
+ for (next = buf; next < lim; next += rtm->rtm_msglen) {
1538
+ struct sockaddr *sa;
1539
+ sigar_net_route_t *route;
1540
+ rtm = (struct rt_msghdr *)next;
1541
+
1542
+ if (rtm->rtm_type != RTM_GET) {
1543
+ continue;
1544
+ }
1545
+
1546
+ sa = (struct sockaddr *)(rtm + 1);
1547
+
1548
+ if (sa->sa_family != AF_INET) {
1549
+ continue;
1550
+ }
1551
+
1552
+ SIGAR_NET_ROUTE_LIST_GROW(routelist);
1553
+ route = &routelist->data[routelist->number++];
1554
+ SIGAR_ZERO(route);
1555
+
1556
+ route->flags = rtm->rtm_flags;
1557
+ if_indextoname(rtm->rtm_index, route->ifname);
1558
+
1559
+ for (bit=RTA_DST;
1560
+ bit && ((char *)sa < lim);
1561
+ bit <<= 1)
1562
+ {
1563
+ if ((rtm->rtm_addrs & bit) == 0) {
1564
+ continue;
1565
+ }
1566
+ switch (bit) {
1567
+ case RTA_DST:
1568
+ sigar_net_address_set(route->destination,
1569
+ rt_s_addr(sa));
1570
+ break;
1571
+ case RTA_GATEWAY:
1572
+ if (sa->sa_family == AF_INET) {
1573
+ sigar_net_address_set(route->gateway,
1574
+ rt_s_addr(sa));
1575
+ }
1576
+ break;
1577
+ case RTA_NETMASK:
1578
+ sigar_net_address_set(route->mask,
1579
+ rt_s_addr(sa));
1580
+ break;
1581
+ case RTA_IFA:
1582
+ break;
1583
+ }
1584
+
1585
+ sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa));
1586
+ }
1587
+ }
1588
+
1589
+ free(buf);
1590
+
1591
+ return SIGAR_OK;
1592
+ }
1593
+
1594
+ int sigar_net_interface_stat_get(sigar_t *sigar,
1595
+ const char *name,
1596
+ sigar_net_interface_stat_t *ifstat)
1597
+ {
1598
+ perfstat_id_t id;
1599
+ perfstat_netinterface_t data;
1600
+
1601
+ sigar_log(sigar, SIGAR_LOG_DEBUG, "[ifstat] using libperfstat");
1602
+
1603
+ SIGAR_SSTRCPY(id.name, name);
1604
+
1605
+ if (perfstat_netinterface(&id, &data, sizeof(data), 1) == 1) {
1606
+ ifstat->rx_bytes = data.ibytes;
1607
+ ifstat->rx_packets = data.ipackets;
1608
+ ifstat->rx_errors = data.ierrors;
1609
+ ifstat->rx_dropped = SIGAR_FIELD_NOTIMPL;
1610
+ ifstat->rx_overruns = SIGAR_FIELD_NOTIMPL;
1611
+ ifstat->rx_frame = SIGAR_FIELD_NOTIMPL;
1612
+
1613
+ ifstat->tx_bytes = data.obytes;
1614
+ ifstat->tx_packets = data.opackets;
1615
+ ifstat->tx_errors = data.oerrors;
1616
+ ifstat->tx_dropped = SIGAR_FIELD_NOTIMPL;
1617
+ ifstat->tx_overruns = SIGAR_FIELD_NOTIMPL;
1618
+ ifstat->tx_collisions = data.collisions;
1619
+ ifstat->tx_carrier = SIGAR_FIELD_NOTIMPL;
1620
+
1621
+ ifstat->speed = data.bitrate;
1622
+
1623
+ return SIGAR_OK;
1624
+ }
1625
+ else {
1626
+ return errno;
1627
+ }
1628
+ }
1629
+
1630
+ int sigar_net_interface_ipv6_config_get(sigar_t *sigar, const char *name,
1631
+ sigar_net_interface_config_t *ifconfig)
1632
+ {
1633
+ int sock;
1634
+ struct in6_ifreq ifr;
1635
+
1636
+ if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1637
+ return errno;
1638
+ }
1639
+
1640
+ SIGAR_SSTRCPY(ifr.ifr_name, name);
1641
+
1642
+ if (ioctl(sock, SIOCGIFADDR6, &ifr) == 0) {
1643
+ struct in6_addr *addr = SIGAR_SIN6_ADDR(&ifr.ifr_Addr);
1644
+
1645
+ sigar_net_address6_set(ifconfig->address6, addr);
1646
+ sigar_net_interface_scope6_set(ifconfig, addr);
1647
+
1648
+ if (ioctl(sock, SIOCGIFNETMASK6, &ifr) == 0) {
1649
+ addr = SIGAR_SIN6_ADDR(&ifr.ifr_Addr);
1650
+ ifconfig->prefix6_length = SIGAR_SIN6(&ifr.ifr_Addr)->sin6_len; /*XXX*/
1651
+ }
1652
+ }
1653
+
1654
+ close(sock);
1655
+ return SIGAR_OK;
1656
+ }
1657
+
1658
+ #define IS_TCP_SERVER(state, flags) \
1659
+ ((flags & SIGAR_NETCONN_SERVER) && (state == TCPS_LISTEN))
1660
+
1661
+ #define IS_TCP_CLIENT(state, flags) \
1662
+ ((flags & SIGAR_NETCONN_CLIENT) && (state != TCPS_LISTEN))
1663
+
1664
+ static int net_conn_get_tcp(sigar_net_connection_walker_t *walker)
1665
+ {
1666
+ sigar_t *sigar = walker->sigar;
1667
+ int flags = walker->flags;
1668
+ int status;
1669
+ struct inpcb tcp_inpcb;
1670
+ struct tcpcb tcpcb;
1671
+ struct inpcb *entry;
1672
+
1673
+ status = kread(sigar, &tcp_inpcb, sizeof(tcp_inpcb),
1674
+ sigar->koffsets[KOFFSET_TCB]);
1675
+
1676
+ if (status != SIGAR_OK) {
1677
+ return status;
1678
+ }
1679
+
1680
+ entry = tcp_inpcb.inp_next;
1681
+ while (entry) {
1682
+ struct inpcb pcb;
1683
+ int state;
1684
+
1685
+ status = kread(sigar, &pcb, sizeof(pcb), (long)entry);
1686
+ if (status != SIGAR_OK) {
1687
+ return status;
1688
+ }
1689
+ status = kread(sigar, &tcpcb, sizeof(tcpcb), (long)pcb.inp_ppcb);
1690
+ if (status != SIGAR_OK) {
1691
+ return status;
1692
+ }
1693
+
1694
+ state = tcpcb.t_state;
1695
+ if ((IS_TCP_SERVER(state, flags) ||
1696
+ IS_TCP_CLIENT(state, flags)))
1697
+ {
1698
+ sigar_net_connection_t conn;
1699
+
1700
+ SIGAR_ZERO(&conn);
1701
+
1702
+ conn.type = SIGAR_NETCONN_TCP;
1703
+
1704
+ sigar_net_address_set(conn.local_address,
1705
+ pcb.inp_laddr.s_addr);
1706
+
1707
+ sigar_net_address_set(conn.remote_address,
1708
+ pcb.inp_faddr.s_addr);
1709
+
1710
+ conn.local_port = ntohs(pcb.inp_lport);
1711
+ conn.remote_port = ntohs(pcb.inp_fport);
1712
+
1713
+ conn.send_queue = conn.receive_queue = SIGAR_FIELD_NOTIMPL;
1714
+
1715
+ switch (state) {
1716
+ case TCPS_CLOSED:
1717
+ conn.state = SIGAR_TCP_CLOSE;
1718
+ break;
1719
+ case TCPS_LISTEN:
1720
+ conn.state = SIGAR_TCP_LISTEN;
1721
+ break;
1722
+ case TCPS_SYN_SENT:
1723
+ conn.state = SIGAR_TCP_SYN_SENT;
1724
+ break;
1725
+ case TCPS_SYN_RECEIVED:
1726
+ conn.state = SIGAR_TCP_SYN_RECV;
1727
+ break;
1728
+ case TCPS_ESTABLISHED:
1729
+ conn.state = SIGAR_TCP_ESTABLISHED;
1730
+ break;
1731
+ case TCPS_CLOSE_WAIT:
1732
+ conn.state = SIGAR_TCP_CLOSE_WAIT;
1733
+ break;
1734
+ case TCPS_FIN_WAIT_1:
1735
+ conn.state = SIGAR_TCP_FIN_WAIT1;
1736
+ break;
1737
+ case TCPS_CLOSING:
1738
+ conn.state = SIGAR_TCP_CLOSING;
1739
+ break;
1740
+ case TCPS_LAST_ACK:
1741
+ conn.state = SIGAR_TCP_LAST_ACK;
1742
+ break;
1743
+ case TCPS_FIN_WAIT_2:
1744
+ conn.state = SIGAR_TCP_FIN_WAIT2;
1745
+ break;
1746
+ case TCPS_TIME_WAIT:
1747
+ conn.state = SIGAR_TCP_TIME_WAIT;
1748
+ break;
1749
+ default:
1750
+ conn.state = SIGAR_TCP_UNKNOWN;
1751
+ break;
1752
+ }
1753
+
1754
+ if (walker->add_connection(walker, &conn) != SIGAR_OK) {
1755
+ break;
1756
+ }
1757
+ }
1758
+
1759
+ entry = pcb.inp_next;
1760
+ if (entry == tcp_inpcb.inp_next) {
1761
+ break;
1762
+ }
1763
+ }
1764
+
1765
+ return SIGAR_OK;
1766
+ }
1767
+
1768
+ int sigar_net_connection_walk(sigar_net_connection_walker_t *walker)
1769
+ {
1770
+ int status;
1771
+
1772
+ if (walker->flags & SIGAR_NETCONN_TCP) {
1773
+ status = net_conn_get_tcp(walker);
1774
+
1775
+ if (status != SIGAR_OK) {
1776
+ return status;
1777
+ }
1778
+ }
1779
+ #if 0
1780
+ if (walker->flags & SIGAR_NETCONN_UDP) {
1781
+ status = net_conn_get_udp(walker);
1782
+
1783
+ if (status != SIGAR_OK) {
1784
+ return status;
1785
+ }
1786
+ }
1787
+ #endif
1788
+ return SIGAR_OK;
1789
+ }
1790
+
1791
+ SIGAR_DECLARE(int)
1792
+ sigar_tcp_get(sigar_t *sigar,
1793
+ sigar_tcp_t *tcp)
1794
+ {
1795
+ perfstat_id_t id;
1796
+ perfstat_protocol_t proto;
1797
+
1798
+ SIGAR_SSTRCPY(id.name, "tcp");
1799
+
1800
+ if (perfstat_protocol(&id, &proto, sizeof(proto), 1) != 1) {
1801
+ return ENOENT;
1802
+ }
1803
+
1804
+ tcp->active_opens = proto.u.tcp.initiated;
1805
+ tcp->passive_opens = proto.u.tcp.accepted;
1806
+ tcp->attempt_fails = proto.u.tcp.dropped;
1807
+ tcp->estab_resets = proto.u.tcp.dropped;
1808
+ tcp->curr_estab = proto.u.tcp.established;
1809
+ tcp->in_segs = proto.u.tcp.ipackets;
1810
+ tcp->out_segs = proto.u.tcp.opackets;
1811
+ tcp->retrans_segs = 0;
1812
+ tcp->in_errs = proto.u.tcp.ierrors;
1813
+ tcp->out_rsts = 0;
1814
+ }
1815
+
1816
+ #define NFS_V2_STAT_SET(type) \
1817
+ nfs->null = proto.u.nfsv2.type.null; \
1818
+ nfs->getattr = proto.u.nfsv2.type.getattr; \
1819
+ nfs->setattr = proto.u.nfsv2.type.setattr; \
1820
+ nfs->root = proto.u.nfsv2.type.root; \
1821
+ nfs->lookup = proto.u.nfsv2.type.lookup; \
1822
+ nfs->readlink = proto.u.nfsv2.type.readlink; \
1823
+ nfs->read = proto.u.nfsv2.type.read; \
1824
+ nfs->writecache = proto.u.nfsv2.type.writecache; \
1825
+ nfs->write = proto.u.nfsv2.type.write; \
1826
+ nfs->create = proto.u.nfsv2.type.create; \
1827
+ nfs->remove = proto.u.nfsv2.type.remove; \
1828
+ nfs->rename = proto.u.nfsv2.type.rename; \
1829
+ nfs->link = proto.u.nfsv2.type.link; \
1830
+ nfs->symlink = proto.u.nfsv2.type.symlink; \
1831
+ nfs->mkdir = proto.u.nfsv2.type.mkdir; \
1832
+ nfs->rmdir = proto.u.nfsv2.type.rmdir; \
1833
+ nfs->readdir = proto.u.nfsv2.type.readdir; \
1834
+ nfs->fsstat = proto.u.nfsv2.type.statfs
1835
+
1836
+ int sigar_nfs_client_v2_get(sigar_t *sigar,
1837
+ sigar_nfs_client_v2_t *nfs)
1838
+ {
1839
+ perfstat_id_t id;
1840
+ perfstat_protocol_t proto;
1841
+
1842
+ SIGAR_SSTRCPY(id.name, "nfsv2");
1843
+
1844
+ if (perfstat_protocol(&id, &proto, sizeof(proto), 1) != 1) {
1845
+ return ENOENT;
1846
+ }
1847
+
1848
+ NFS_V2_STAT_SET(client);
1849
+
1850
+ return SIGAR_OK;
1851
+ }
1852
+
1853
+ int sigar_nfs_server_v2_get(sigar_t *sigar,
1854
+ sigar_nfs_server_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(server);
1866
+
1867
+ return SIGAR_OK;
1868
+ }
1869
+
1870
+ #define NFS_V3_STAT_SET(type) \
1871
+ nfs->null = proto.u.nfsv3.type.null; \
1872
+ nfs->getattr = proto.u.nfsv3.type.getattr; \
1873
+ nfs->setattr = proto.u.nfsv3.type.setattr; \
1874
+ nfs->lookup = proto.u.nfsv3.type.lookup; \
1875
+ nfs->access = proto.u.nfsv3.type.access; \
1876
+ nfs->readlink = proto.u.nfsv3.type.readlink; \
1877
+ nfs->read = proto.u.nfsv3.type.read; \
1878
+ nfs->write = proto.u.nfsv3.type.write; \
1879
+ nfs->create = proto.u.nfsv3.type.create; \
1880
+ nfs->mkdir = proto.u.nfsv3.type.mkdir; \
1881
+ nfs->symlink = proto.u.nfsv3.type.symlink; \
1882
+ nfs->mknod = proto.u.nfsv3.type.mknod; \
1883
+ nfs->remove = proto.u.nfsv3.type.remove; \
1884
+ nfs->rmdir = proto.u.nfsv3.type.rmdir; \
1885
+ nfs->rename = proto.u.nfsv3.type.rename; \
1886
+ nfs->link = proto.u.nfsv3.type.link; \
1887
+ nfs->readdir = proto.u.nfsv3.type.readdir; \
1888
+ nfs->readdirplus = proto.u.nfsv3.type.readdirplus; \
1889
+ nfs->fsstat = proto.u.nfsv3.type.fsstat; \
1890
+ nfs->fsinfo = proto.u.nfsv3.type.fsinfo; \
1891
+ nfs->pathconf = proto.u.nfsv3.type.pathconf; \
1892
+ nfs->commit = proto.u.nfsv3.type.commit
1893
+
1894
+ int sigar_nfs_client_v3_get(sigar_t *sigar,
1895
+ sigar_nfs_client_v3_t *nfs)
1896
+ {
1897
+ perfstat_id_t id;
1898
+ perfstat_protocol_t proto;
1899
+
1900
+ SIGAR_SSTRCPY(id.name, "nfsv3");
1901
+
1902
+ if (perfstat_protocol(&id, &proto, sizeof(proto), 1) != 1) {
1903
+ return ENOENT;
1904
+ }
1905
+
1906
+ NFS_V3_STAT_SET(client);
1907
+
1908
+ return SIGAR_OK;
1909
+ }
1910
+
1911
+ int sigar_nfs_server_v3_get(sigar_t *sigar,
1912
+ sigar_nfs_server_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(server);
1924
+
1925
+ return SIGAR_OK;
1926
+ }
1927
+
1928
+ #include <net/if_arp.h>
1929
+ /*
1930
+ * cannot find any related aix docs on reading the ARP table,
1931
+ * this impl was gleaned from the above .h file and truss -f arp -an
1932
+ */
1933
+ int sigar_arp_list_get(sigar_t *sigar,
1934
+ sigar_arp_list_t *arplist)
1935
+ {
1936
+ int status = SIGAR_OK;
1937
+ long arptabsize;
1938
+ int i, size, retval;
1939
+ struct arptab *arptabp;
1940
+
1941
+ size = sizeof(arptabsize);
1942
+ retval = getkerninfo(KINFO_READ, &arptabsize, &size,
1943
+ sigar->koffsets[KOFFSET_ARPTABSIZE]);
1944
+ if (retval != sizeof(arptabsize)) {
1945
+ return errno;
1946
+ }
1947
+
1948
+ size = sizeof(arptabp);
1949
+ retval = getkerninfo(KINFO_READ, &arptabp, &size,
1950
+ sigar->koffsets[KOFFSET_ARPTABP]);
1951
+ if (retval != sizeof(arptabp)) {
1952
+ return errno;
1953
+ }
1954
+
1955
+ sigar_arp_list_create(arplist);
1956
+ status = SIGAR_OK;
1957
+
1958
+ for (i=0; i<arptabsize; i++) {
1959
+ struct arptab ent;
1960
+ struct ifnet ifp;
1961
+ sigar_arp_t *arp;
1962
+
1963
+ size = sizeof(ent);
1964
+ retval = getkerninfo(KINFO_READ, &ent, &size, arptabp + i);
1965
+ if (retval != sizeof(ent)) {
1966
+ status = errno;
1967
+ break;
1968
+ }
1969
+
1970
+ if (ent.at_flags == 0) {
1971
+ continue; /* empty bucket */
1972
+ }
1973
+
1974
+ size = sizeof(ifp);
1975
+ retval = getkerninfo(KINFO_READ, &ifp, &size, ent.at_ifp);
1976
+ if (retval != sizeof(ifp)) {
1977
+ status = errno;
1978
+ break;
1979
+ }
1980
+
1981
+ SIGAR_ARP_LIST_GROW(arplist);
1982
+ arp = &arplist->data[arplist->number++];
1983
+
1984
+ sigar_net_address_set(arp->address,
1985
+ ent.at_iaddr.s_addr);
1986
+
1987
+ sigar_net_address_mac_set(arp->hwaddr,
1988
+ ent.hwaddr,
1989
+ sizeof(arp->hwaddr.addr.mac));
1990
+
1991
+ if_indextoname(ifp.if_index, arp->ifname);
1992
+
1993
+ arp->flags = ent.at_flags;
1994
+ SIGAR_SSTRCPY(arp->type, "ether"); /* XXX ifp.if_type */
1995
+ }
1996
+
1997
+ if (status != SIGAR_OK) {
1998
+ sigar_arp_list_destroy(sigar, arplist);
1999
+ }
2000
+
2001
+ return status;
2002
+ }
2003
+
2004
+ /* derived from pidentd's k_aix432.c */
2005
+ int sigar_proc_port_get(sigar_t *sigar, int protocol,
2006
+ unsigned long port, sigar_pid_t *pidp)
2007
+ {
2008
+ struct procsinfo pinfo;
2009
+ struct fdsinfo finfo;
2010
+ pid_t pid = 0;
2011
+ int type;
2012
+
2013
+ switch (protocol) {
2014
+ case SIGAR_NETCONN_TCP:
2015
+ type = IPPROTO_TCP;
2016
+ break;
2017
+ case SIGAR_NETCONN_UDP:
2018
+ type = IPPROTO_UDP;
2019
+ break;
2020
+ default:
2021
+ return SIGAR_ENOTIMPL;
2022
+ }
2023
+
2024
+ for (;;) {
2025
+ int fd, status;
2026
+ int num = getprocs(&pinfo, sizeof(pinfo),
2027
+ &finfo, sizeof(finfo),
2028
+ &pid, 1);
2029
+
2030
+ if (num == 0) {
2031
+ break;
2032
+ }
2033
+
2034
+ if ((pinfo.pi_state == 0) || (pinfo.pi_state == SZOMB)) {
2035
+ continue;
2036
+ }
2037
+
2038
+ for (fd = 0; fd < pinfo.pi_maxofile; fd++) {
2039
+ struct file file;
2040
+ struct socket socket, *sockp;
2041
+ struct protosw protosw;
2042
+ struct domain domain;
2043
+ struct inpcb inpcb;
2044
+ long ptr;
2045
+
2046
+ if (!(ptr = (long)finfo.pi_ufd[fd].fp)) {
2047
+ continue;
2048
+ }
2049
+
2050
+ status = kread(sigar, &file, sizeof(file), ptr);
2051
+ if (status != SIGAR_OK) {
2052
+ continue;
2053
+ }
2054
+
2055
+ if (file.f_type != DTYPE_SOCKET) {
2056
+ continue;
2057
+ }
2058
+
2059
+ if (!(sockp = (struct socket *)file.f_data)) {
2060
+ continue;
2061
+ }
2062
+
2063
+ status = kread(sigar, &socket, sizeof(socket), (long)sockp);
2064
+ if (status != SIGAR_OK) {
2065
+ continue;
2066
+ }
2067
+
2068
+ if (!(ptr = (long)socket.so_proto)) {
2069
+ continue;
2070
+ }
2071
+
2072
+ status = kread(sigar, &protosw, sizeof(protosw), ptr);
2073
+ if (status != SIGAR_OK) {
2074
+ continue;
2075
+ }
2076
+
2077
+ if (protosw.pr_protocol != type) {
2078
+ continue;
2079
+ }
2080
+
2081
+ if (!(ptr = (long)protosw.pr_domain)) {
2082
+ continue;
2083
+ }
2084
+
2085
+ status = kread(sigar, &domain, sizeof(domain), ptr);
2086
+ if (status != SIGAR_OK) {
2087
+ continue;
2088
+ }
2089
+
2090
+ if ((domain.dom_family != AF_INET) &&
2091
+ domain.dom_family != AF_INET6)
2092
+ {
2093
+ continue;
2094
+ }
2095
+
2096
+ if (!(ptr = (long)socket.so_pcb)) {
2097
+ continue;
2098
+ }
2099
+
2100
+ status = kread(sigar, &inpcb, sizeof(inpcb), ptr);
2101
+ if (status != SIGAR_OK) {
2102
+ continue;
2103
+ }
2104
+
2105
+ if (sockp != inpcb.inp_socket) {
2106
+ continue;
2107
+ }
2108
+
2109
+ if (inpcb.inp_lport != port) {
2110
+ continue;
2111
+ }
2112
+
2113
+ *pidp = pinfo.pi_pid;
2114
+
2115
+ return SIGAR_OK;
2116
+ }
2117
+ }
2118
+
2119
+ return ENOENT;
2120
+ }
2121
+
2122
+ int sigar_os_sys_info_get(sigar_t *sigar,
2123
+ sigar_sys_info_t *sysinfo)
2124
+ {
2125
+ struct utsname name;
2126
+
2127
+ uname(&name);
2128
+
2129
+ SIGAR_SSTRCPY(sysinfo->vendor, "IBM");
2130
+ SIGAR_SSTRCPY(sysinfo->arch, get_cpu_arch());
2131
+ /* utsname.machine is a sequence number */
2132
+ /* XXX odm might have something better */
2133
+ snprintf(sysinfo->machine,
2134
+ sizeof(sysinfo->machine),
2135
+ "%s %s",
2136
+ sysinfo->arch, get_cpu_model());
2137
+
2138
+ snprintf(sysinfo->version,
2139
+ sizeof(sysinfo->version),
2140
+ "%s.%s",
2141
+ name.version, name.release);
2142
+
2143
+ SIGAR_SSTRCPY(sysinfo->vendor_version, sysinfo->version);
2144
+
2145
+ snprintf(sysinfo->description,
2146
+ sizeof(sysinfo->description),
2147
+ "%s %s",
2148
+ sysinfo->name, sysinfo->version);
2149
+
2150
+ return SIGAR_OK;
2151
+ }