sigar 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,216 @@
1
+ /*
2
+ * Copyright (c) 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
+ #include "sigar.h"
18
+ #include "sigar_private.h"
19
+ #include "sigar_util.h"
20
+
21
+ #ifdef WIN32
22
+ #include <windows.h>
23
+ #endif
24
+
25
+ #include <signal.h>
26
+ #include <errno.h>
27
+
28
+ SIGAR_DECLARE(int) sigar_proc_kill(sigar_pid_t pid, int signum)
29
+ {
30
+ #ifdef WIN32
31
+ int status = -1;
32
+ HANDLE proc =
33
+ OpenProcess(PROCESS_ALL_ACCESS,
34
+ TRUE, (DWORD)pid);
35
+
36
+ if (proc) {
37
+ switch (signum) {
38
+ case 0:
39
+ status = SIGAR_OK;
40
+ break;
41
+ default:
42
+ if (TerminateProcess(proc, signum)) {
43
+ status = SIGAR_OK;
44
+ }
45
+ break;
46
+ }
47
+
48
+ CloseHandle(proc);
49
+
50
+ if (status == SIGAR_OK) {
51
+ return SIGAR_OK;
52
+ }
53
+ }
54
+ return GetLastError();
55
+ #else
56
+ if (kill(pid, signum) == -1) {
57
+ return errno;
58
+ }
59
+ return SIGAR_OK;
60
+ #endif
61
+ }
62
+
63
+ SIGAR_DECLARE(int) sigar_signum_get(char *name)
64
+ {
65
+ if (strnEQ(name, "SIG", 3)) {
66
+ name += 3;
67
+ }
68
+
69
+ switch (*name) {
70
+ case 'A':
71
+ #ifdef SIGABRT
72
+ if (strEQ(name, "ABRT")) return SIGABRT;
73
+ #endif
74
+ #ifdef SIGALRM
75
+ if (strEQ(name, "ALRM")) return SIGALRM;
76
+ #endif
77
+ break;
78
+ case 'B':
79
+ #ifdef SIGBUS
80
+ if (strEQ(name, "BUS")) return SIGBUS;
81
+ #endif
82
+ break;
83
+ case 'C':
84
+ #ifdef SIGCONT
85
+ if (strEQ(name, "CONT")) return SIGCONT;
86
+ #endif
87
+ #ifdef SIGCHLD
88
+ if (strEQ(name, "CHLD")) return SIGCHLD;
89
+ #endif
90
+ #ifdef SIGCLD
91
+ if (strEQ(name, "CLD")) return SIGCLD;
92
+ #endif
93
+ break;
94
+ case 'E':
95
+ #ifdef SIGEMT
96
+ if (strEQ(name, "EMT")) return SIGEMT;
97
+ #endif
98
+ break;
99
+ case 'F':
100
+ #ifdef SIGFPE
101
+ if (strEQ(name, "FPE")) return SIGFPE;
102
+ #endif
103
+ break;
104
+ case 'H':
105
+ #ifdef SIGHUP
106
+ if (strEQ(name, "HUP")) return SIGHUP;
107
+ #endif
108
+ break;
109
+ case 'I':
110
+ #ifdef SIGINT
111
+ if (strEQ(name, "INT")) return SIGINT;
112
+ #endif
113
+ #ifdef SIGILL
114
+ if (strEQ(name, "ILL")) return SIGILL;
115
+ #endif
116
+ #ifdef SIGIOT
117
+ if (strEQ(name, "IOT")) return SIGIOT;
118
+ #endif
119
+ #ifdef SIGIO
120
+ if (strEQ(name, "IO")) return SIGIO;
121
+ #endif
122
+ #ifdef SIGINFO
123
+ if (strEQ(name, "INFO")) return SIGINFO;
124
+ #endif
125
+ break;
126
+ case 'K':
127
+ #ifdef SIGKILL
128
+ if (strEQ(name, "KILL")) return SIGKILL;
129
+ #endif
130
+ break;
131
+ case 'P':
132
+ #ifdef SIGPOLL
133
+ if (strEQ(name, "POLL")) return SIGPOLL;
134
+ #endif
135
+ #ifdef SIGPIPE
136
+ if (strEQ(name, "PIPE")) return SIGPIPE;
137
+ #endif
138
+ #ifdef SIGPROF
139
+ if (strEQ(name, "PROF")) return SIGPROF;
140
+ #endif
141
+ #ifdef SIGPWR
142
+ if (strEQ(name, "PWR")) return SIGPWR;
143
+ #endif
144
+ break;
145
+ case 'Q':
146
+ #ifdef SIGQUIT
147
+ if (strEQ(name, "QUIT")) return SIGQUIT;
148
+ #endif
149
+ break;
150
+ case 'S':
151
+ #ifdef SIGSEGV
152
+ if (strEQ(name, "SEGV")) return SIGSEGV;
153
+ #endif
154
+ #ifdef SIGSYS
155
+ if (strEQ(name, "SYS")) return SIGSYS;
156
+ #endif
157
+ #ifdef SIGSTOP
158
+ if (strEQ(name, "STOP")) return SIGSTOP;
159
+ #endif
160
+ #ifdef SIGSTKFLT
161
+ if (strEQ(name, "STKFLT")) return SIGSTKFLT;
162
+ #endif
163
+ break;
164
+ case 'T':
165
+ #ifdef SIGTRAP
166
+ if (strEQ(name, "TRAP")) return SIGTRAP;
167
+ #endif
168
+ #ifdef SIGTERM
169
+ if (strEQ(name, "TERM")) return SIGTERM;
170
+ #endif
171
+ #ifdef SIGTSTP
172
+ if (strEQ(name, "TSTP")) return SIGTSTP;
173
+ #endif
174
+ #ifdef SIGTTIN
175
+ if (strEQ(name, "TTIN")) return SIGTTIN;
176
+ #endif
177
+ #ifdef SIGTTOU
178
+ if (strEQ(name, "TTOU")) return SIGTTOU;
179
+ #endif
180
+ break;
181
+ case 'U':
182
+ #ifdef SIGURG
183
+ if (strEQ(name, "URG")) return SIGURG;
184
+ #endif
185
+ #ifdef SIGUSR1
186
+ if (strEQ(name, "USR1")) return SIGUSR1;
187
+ #endif
188
+ #ifdef SIGUSR2
189
+ if (strEQ(name, "USR2")) return SIGUSR2;
190
+ #endif
191
+ break;
192
+ case 'V':
193
+ #ifdef SIGVTALRM
194
+ if (strEQ(name, "VTALRM")) return SIGVTALRM;
195
+ #endif
196
+ break;
197
+ case 'W':
198
+ #ifdef SIGWINCH
199
+ if (strEQ(name, "WINCH")) return SIGWINCH;
200
+ #endif
201
+ break;
202
+ case 'X':
203
+ #ifdef SIGXCPU
204
+ if (strEQ(name, "XCPU")) return SIGXCPU;
205
+ #endif
206
+ #ifdef SIGXFSZ
207
+ if (strEQ(name, "XFSZ")) return SIGXFSZ;
208
+ #endif
209
+ break;
210
+ default:
211
+ break;
212
+ }
213
+
214
+ return -1;
215
+ }
216
+
@@ -0,0 +1,1060 @@
1
+ /*
2
+ * Copyright (c) 2004-2009 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
+ #include <stdio.h>
19
+ #include <stdlib.h>
20
+ #include <errno.h>
21
+ #include <fcntl.h>
22
+ #include <assert.h>
23
+
24
+ #include "sigar.h"
25
+ #include "sigar_private.h"
26
+ #include "sigar_util.h"
27
+ #include "sigar_os.h"
28
+
29
+ #ifndef WIN32
30
+
31
+ #include <dirent.h>
32
+ #include <sys/stat.h>
33
+
34
+ SIGAR_INLINE char *sigar_uitoa(char *buf, unsigned int n, int *len)
35
+ {
36
+ char *start = buf + UITOA_BUFFER_SIZE - 1;
37
+
38
+ *start = 0;
39
+
40
+ do {
41
+ *--start = '0' + (n % 10);
42
+ ++*len;
43
+ n /= 10;
44
+ } while (n);
45
+
46
+ return start;
47
+ }
48
+
49
+ SIGAR_INLINE char *sigar_skip_line(char *buffer, int buflen)
50
+ {
51
+ char *ptr = buflen ?
52
+ (char *)memchr(buffer, '\n', buflen) : /* bleh */
53
+ strchr(buffer, '\n');
54
+ return ++ptr;
55
+ }
56
+
57
+ SIGAR_INLINE char *sigar_skip_token(char *p)
58
+ {
59
+ while (sigar_isspace(*p)) p++;
60
+ while (*p && !sigar_isspace(*p)) p++;
61
+ return p;
62
+ }
63
+
64
+ SIGAR_INLINE char *sigar_skip_multiple_token(char *p, int count)
65
+ {
66
+ int i;
67
+
68
+ for (i = 0; i < count; i++) {
69
+ p = sigar_skip_token(p);
70
+ }
71
+
72
+ return p;
73
+ }
74
+
75
+ char *sigar_getword(char **line, char stop)
76
+ {
77
+ char *pos = *line;
78
+ int len;
79
+ char *res;
80
+
81
+ while ((*pos != stop) && *pos) {
82
+ ++pos;
83
+ }
84
+
85
+ len = pos - *line;
86
+ res = malloc(len + 1);
87
+ memcpy(res, *line, len);
88
+ res[len] = 0;
89
+
90
+ if (stop) {
91
+ while (*pos == stop) {
92
+ ++pos;
93
+ }
94
+ }
95
+
96
+ *line = pos;
97
+
98
+ return res;
99
+ }
100
+
101
+ /* avoiding sprintf */
102
+
103
+ char *sigar_proc_filename(char *buffer, int buflen,
104
+ sigar_pid_t bigpid,
105
+ const char *fname, int fname_len)
106
+ {
107
+ int len = 0;
108
+ char *ptr = buffer;
109
+ unsigned int pid = (unsigned int)bigpid; /* XXX -- This isn't correct */
110
+ char pid_buf[UITOA_BUFFER_SIZE];
111
+ char *pid_str = sigar_uitoa(pid_buf, pid, &len);
112
+
113
+ assert((unsigned int)buflen >=
114
+ (SSTRLEN(PROCP_FS_ROOT) + UITOA_BUFFER_SIZE + fname_len + 1));
115
+
116
+ memcpy(ptr, PROCP_FS_ROOT, SSTRLEN(PROCP_FS_ROOT));
117
+ ptr += SSTRLEN(PROCP_FS_ROOT);
118
+
119
+ memcpy(ptr, pid_str, len);
120
+ ptr += len;
121
+
122
+ memcpy(ptr, fname, fname_len);
123
+ ptr += fname_len;
124
+ *ptr = '\0';
125
+
126
+ return buffer;
127
+ }
128
+
129
+ int sigar_proc_file2str(char *buffer, int buflen,
130
+ sigar_pid_t pid,
131
+ const char *fname,
132
+ int fname_len)
133
+ {
134
+ int retval;
135
+
136
+ buffer = sigar_proc_filename(buffer, buflen, pid,
137
+ fname, fname_len);
138
+
139
+ retval = sigar_file2str(buffer, buffer, buflen);
140
+
141
+ if (retval != SIGAR_OK) {
142
+ switch (retval) {
143
+ case ENOENT:
144
+ retval = ESRCH; /* no such process */
145
+ default:
146
+ break;
147
+ }
148
+ }
149
+
150
+ return retval;
151
+ }
152
+
153
+ int sigar_proc_list_procfs_get(sigar_t *sigar,
154
+ sigar_proc_list_t *proclist)
155
+ {
156
+ DIR *dirp = opendir("/proc");
157
+ struct dirent *ent;
158
+ #ifdef HAVE_READDIR_R
159
+ struct dirent dbuf;
160
+ #endif
161
+
162
+ if (!dirp) {
163
+ return errno;
164
+ }
165
+
166
+ #ifdef HAVE_READDIR_R
167
+ while (readdir_r(dirp, &dbuf, &ent) == 0) {
168
+ if (ent == NULL) {
169
+ break;
170
+ }
171
+ #else
172
+ while ((ent = readdir(dirp))) {
173
+ #endif
174
+ if (!sigar_isdigit(*ent->d_name)) {
175
+ continue;
176
+ }
177
+
178
+ /* XXX: more sanity checking */
179
+
180
+ SIGAR_PROC_LIST_GROW(proclist);
181
+
182
+ proclist->data[proclist->number++] =
183
+ strtoul(ent->d_name, NULL, 10);
184
+ }
185
+
186
+ closedir(dirp);
187
+
188
+ return SIGAR_OK;
189
+ }
190
+
191
+ int sigar_proc_fd_count(sigar_t *sigar, sigar_pid_t pid,
192
+ sigar_uint64_t *total)
193
+ {
194
+ DIR *dirp;
195
+ struct dirent *ent;
196
+ #ifdef HAVE_READDIR_R
197
+ struct dirent dbuf;
198
+ #endif
199
+ char name[BUFSIZ];
200
+
201
+ (void)SIGAR_PROC_FILENAME(name, pid, "/fd");
202
+
203
+ *total = 0;
204
+
205
+ if (!(dirp = opendir(name))) {
206
+ return errno;
207
+ }
208
+
209
+ #ifdef HAVE_READDIR_R
210
+ while (readdir_r(dirp, &dbuf, &ent) == 0) {
211
+ if (ent == NULL) {
212
+ break;
213
+ }
214
+ #else
215
+ while ((ent = readdir(dirp))) {
216
+ #endif
217
+ if (!sigar_isdigit(*ent->d_name)) {
218
+ continue;
219
+ }
220
+
221
+ (*total)++;
222
+ }
223
+
224
+ closedir(dirp);
225
+
226
+ return SIGAR_OK;
227
+ }
228
+
229
+ int sigar_procfs_args_get(sigar_t *sigar, sigar_pid_t pid,
230
+ sigar_proc_args_t *procargs)
231
+ {
232
+ char buffer[9086], *buf=NULL, *ptr;
233
+ int fd, len, total=0;
234
+
235
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/cmdline");
236
+
237
+ if ((fd = open(buffer, O_RDONLY)) < 0) {
238
+ if (errno == ENOENT) {
239
+ return ESRCH;
240
+ }
241
+ return errno;
242
+ }
243
+
244
+ buffer[0] = '\0';
245
+
246
+ /* XXX: possible to get rid of some mallocs here.
247
+ * but, unlikely this will be called often so it
248
+ * might not even matter much.
249
+ */
250
+ while ((len = read(fd, buffer, sizeof(buffer)-1)) > 0) {
251
+ if (len == 0) {
252
+ break;
253
+ }
254
+ buf = realloc(buf, total+len+1);
255
+ memcpy(buf+total, buffer, len);
256
+ total += len;
257
+ }
258
+
259
+ close(fd);
260
+
261
+ /* e.g. /proc/2/cmdline */
262
+ if (total == 0) {
263
+ procargs->number = 0;
264
+ return SIGAR_OK;
265
+ }
266
+
267
+ buf[total] = '\0';
268
+ ptr = buf;
269
+
270
+ while (total > 0) {
271
+ int alen = strlen(ptr)+1;
272
+ char *arg = malloc(alen);
273
+
274
+ SIGAR_PROC_ARGS_GROW(procargs);
275
+ memcpy(arg, ptr, alen);
276
+
277
+ procargs->data[procargs->number++] = arg;
278
+
279
+ total -= alen;
280
+ if (total > 0) {
281
+ ptr += alen;
282
+ }
283
+ }
284
+
285
+ free(buf);
286
+
287
+ return SIGAR_OK;
288
+ }
289
+
290
+ #endif /* WIN32 */
291
+
292
+ /* from httpd/server/util.c */
293
+ char *sigar_strcasestr(const char *s1, const char *s2)
294
+ {
295
+ char *p1, *p2;
296
+ if (*s2 == '\0') {
297
+ /* an empty s2 */
298
+ return((char *)s1);
299
+ }
300
+ while(1) {
301
+ for ( ; (*s1 != '\0') && (sigar_tolower(*s1) != sigar_tolower(*s2)); s1++);
302
+ if (*s1 == '\0') {
303
+ return(NULL);
304
+ }
305
+ /* found first character of s2, see if the rest matches */
306
+ p1 = (char *)s1;
307
+ p2 = (char *)s2;
308
+ for (++p1, ++p2; sigar_tolower(*p1) == sigar_tolower(*p2); ++p1, ++p2) {
309
+ if (*p1 == '\0') {
310
+ /* both strings ended together */
311
+ return((char *)s1);
312
+ }
313
+ }
314
+ if (*p2 == '\0') {
315
+ /* second string ended, a match */
316
+ break;
317
+ }
318
+ /* didn't find a match here, try starting at next character in s1 */
319
+ s1++;
320
+ }
321
+ return((char *)s1);
322
+ }
323
+
324
+ int sigar_mem_calc_ram(sigar_t *sigar, sigar_mem_t *mem)
325
+ {
326
+ sigar_int64_t total = mem->total / 1024, diff;
327
+ sigar_uint64_t lram = (mem->total / (1024 * 1024));
328
+ int ram = (int)lram; /* must cast after division */
329
+ int remainder = ram % 8;
330
+
331
+ if (remainder > 0) {
332
+ ram += (8 - remainder);
333
+ }
334
+
335
+ mem->ram = ram;
336
+
337
+ diff = total - (mem->actual_free / 1024);
338
+ mem->used_percent =
339
+ (double)(diff * 100) / total;
340
+
341
+ diff = total - (mem->actual_used / 1024);
342
+ mem->free_percent =
343
+ (double)(diff * 100) / total;
344
+
345
+ return ram;
346
+ }
347
+
348
+ #ifndef WIN32
349
+
350
+ sigar_iodev_t *sigar_iodev_get(sigar_t *sigar,
351
+ const char *dirname)
352
+ {
353
+ sigar_cache_entry_t *entry;
354
+ struct stat sb;
355
+ sigar_uint64_t id;
356
+ sigar_file_system_list_t fslist;
357
+ int i, status, is_dev=0;
358
+ int debug = SIGAR_LOG_IS_DEBUG(sigar);
359
+ char dev_name[SIGAR_FS_NAME_LEN];
360
+
361
+ if (!sigar->fsdev) {
362
+ sigar->fsdev = sigar_cache_new(15);
363
+ }
364
+
365
+ if (*dirname != '/') {
366
+ snprintf(dev_name, sizeof(dev_name),
367
+ SIGAR_DEV_PREFIX "%s", dirname);
368
+ dirname = dev_name;
369
+ is_dev = 1;
370
+ }
371
+ else if (SIGAR_NAME_IS_DEV(dirname)) {
372
+ is_dev = 1;
373
+ }
374
+
375
+ if (stat(dirname, &sb) < 0) {
376
+ if (debug) {
377
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
378
+ "[iodev] stat(%s) failed",
379
+ dirname);
380
+ }
381
+ return NULL;
382
+ }
383
+
384
+ id = SIGAR_FSDEV_ID(sb);
385
+
386
+ entry = sigar_cache_get(sigar->fsdev, id);
387
+
388
+ if (entry->value != NULL) {
389
+ return (sigar_iodev_t *)entry->value;
390
+ }
391
+
392
+ if (is_dev) {
393
+ sigar_iodev_t *iodev;
394
+ entry->value = iodev = malloc(sizeof(*iodev));
395
+ SIGAR_ZERO(iodev);
396
+ SIGAR_SSTRCPY(iodev->name, dirname);
397
+ if (debug) {
398
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
399
+ "[iodev] %s is_dev=true", dirname);
400
+ }
401
+ return iodev;
402
+ }
403
+
404
+ status = sigar_file_system_list_get(sigar, &fslist);
405
+
406
+ if (status != SIGAR_OK) {
407
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
408
+ "[iodev] file_system_list failed: %s",
409
+ sigar_strerror(sigar, status));
410
+ return NULL;
411
+ }
412
+
413
+ for (i=0; i<fslist.number; i++) {
414
+ sigar_file_system_t *fsp = &fslist.data[i];
415
+
416
+ if (fsp->type == SIGAR_FSTYPE_LOCAL_DISK) {
417
+ int retval = stat(fsp->dir_name, &sb);
418
+ sigar_cache_entry_t *ent;
419
+
420
+ if (retval < 0) {
421
+ if (debug) {
422
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
423
+ "[iodev] inode stat(%s) failed",
424
+ fsp->dir_name);
425
+ }
426
+ continue; /* cant cache w/o inode */
427
+ }
428
+
429
+ ent = sigar_cache_get(sigar->fsdev, SIGAR_FSDEV_ID(sb));
430
+ if (ent->value) {
431
+ continue; /* already cached */
432
+ }
433
+
434
+ if (SIGAR_NAME_IS_DEV(fsp->dev_name)) {
435
+ sigar_iodev_t *iodev;
436
+ ent->value = iodev = malloc(sizeof(*iodev));
437
+ SIGAR_ZERO(iodev);
438
+ iodev->is_partition = 1;
439
+ SIGAR_SSTRCPY(iodev->name, fsp->dev_name);
440
+
441
+ if (debug) {
442
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
443
+ "[iodev] map %s -> %s",
444
+ fsp->dir_name, iodev->name);
445
+ }
446
+ }
447
+ }
448
+ }
449
+
450
+ sigar_file_system_list_destroy(sigar, &fslist);
451
+
452
+ if (entry->value &&
453
+ (((sigar_iodev_t *)entry->value)->name[0] != '\0'))
454
+ {
455
+ return (sigar_iodev_t *)entry->value;
456
+ }
457
+ else {
458
+ return NULL;
459
+ }
460
+ }
461
+ #endif
462
+
463
+ double sigar_file_system_usage_calc_used(sigar_t *sigar,
464
+ sigar_file_system_usage_t *fsusage)
465
+ {
466
+ /*
467
+ * win32 will not convert __uint64 to double.
468
+ * convert to KB then do unsigned long -> double.
469
+ */
470
+ sigar_uint64_t b_used = (fsusage->total - fsusage->free) / 1024;
471
+ sigar_uint64_t b_avail = fsusage->avail / 1024;
472
+ unsigned long utotal = b_used + b_avail;
473
+ unsigned long used = b_used;
474
+
475
+ if (utotal != 0) {
476
+ unsigned long u100 = used * 100;
477
+ double pct = u100 / utotal +
478
+ ((u100 % utotal != 0) ? 1 : 0);
479
+ return pct / 100;
480
+ }
481
+
482
+ return 0;
483
+ }
484
+
485
+ typedef struct {
486
+ sigar_uint32_t eax;
487
+ sigar_uint32_t ebx;
488
+ sigar_uint32_t ecx;
489
+ sigar_uint32_t edx;
490
+ } sigar_cpuid_t;
491
+
492
+ #if defined(__GNUC__) && !defined(__sun)
493
+
494
+ # if defined(__i386__)
495
+ # define SIGAR_HAS_CPUID
496
+ static void sigar_cpuid(sigar_uint32_t request, sigar_cpuid_t *id)
497
+ {
498
+ /* derived from: */
499
+ /* http://svn.red-bean.com/repos/minor/trunk/gc/barriers-ia-32.c */
500
+ asm volatile ("mov %%ebx, %%esi\n\t"
501
+ "cpuid\n\t"
502
+ "xchgl %%ebx, %%esi"
503
+ : "=a" (id->eax),
504
+ "=S" (id->ebx),
505
+ "=c" (id->ecx),
506
+ "=d" (id->edx)
507
+ : "0" (request)
508
+ : "memory");
509
+ }
510
+ # elif defined(__amd64__)
511
+ # define SIGAR_HAS_CPUID
512
+ static void sigar_cpuid(sigar_uint32_t request,
513
+ sigar_cpuid_t *id)
514
+ {
515
+ /* http://svn.red-bean.com/repos/minor/trunk/gc/barriers-amd64.c */
516
+ asm volatile ("cpuid\n\t"
517
+ : "=a" (id->eax),
518
+ "=b" (id->ebx),
519
+ "=c" (id->ecx),
520
+ "=d" (id->edx)
521
+ : "0" (request)
522
+ : "memory");
523
+ }
524
+ # endif
525
+ #elif defined(WIN32)
526
+ # ifdef _M_X64
527
+ # include <intrin.h>
528
+ # define SIGAR_HAS_CPUID
529
+ static void sigar_cpuid(sigar_uint32_t request,
530
+ sigar_cpuid_t *id)
531
+ {
532
+ sigar_uint32_t info[4];
533
+ __cpuid(info, request); /* as of MSVC 7 */
534
+ memcpy(id, &info[0], sizeof(info));
535
+ }
536
+ # else
537
+ # define SIGAR_HAS_CPUID
538
+ static void sigar_cpuid(sigar_uint32_t request,
539
+ sigar_cpuid_t *id)
540
+ {
541
+ __asm {
542
+ mov edi, id
543
+ mov eax, [edi].eax
544
+ mov ecx, [edi].ecx
545
+ cpuid
546
+ mov [edi].eax, eax
547
+ mov [edi].ebx, ebx
548
+ mov [edi].ecx, ecx
549
+ mov [edi].edx, edx
550
+ }
551
+ }
552
+ # endif
553
+ #endif
554
+
555
+ #define INTEL_ID 0x756e6547
556
+ #define AMD_ID 0x68747541
557
+
558
+ int sigar_cpu_core_count(sigar_t *sigar)
559
+ {
560
+ #if defined(SIGAR_HAS_CPUID)
561
+ sigar_cpuid_t id;
562
+
563
+ if (sigar->lcpu == -1) {
564
+ sigar->lcpu = 1;
565
+
566
+ sigar_cpuid(0, &id);
567
+
568
+ if ((id.ebx == INTEL_ID) || (id.ebx == AMD_ID)) {
569
+ sigar_cpuid(1, &id);
570
+
571
+ if (id.edx & (1<<28)) {
572
+ sigar->lcpu = (id.ebx & 0x00FF0000) >> 16;
573
+ }
574
+ }
575
+
576
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
577
+ "[cpu] %d cores per socket", sigar->lcpu);
578
+ }
579
+
580
+ return sigar->lcpu;
581
+ #elif defined(__sun) || defined(__hpux) || defined(_AIX)
582
+ return 1;
583
+ #else
584
+ sigar->lcpu = 1;
585
+ return sigar->lcpu;
586
+ #endif
587
+ }
588
+
589
+ int sigar_cpu_core_rollup(sigar_t *sigar)
590
+ {
591
+ #ifdef SIGAR_HAS_CPUID
592
+ int log_rollup =
593
+ SIGAR_LOG_IS_DEBUG(sigar) &&
594
+ (sigar->lcpu == -1);
595
+
596
+ (void)sigar_cpu_core_count(sigar);
597
+
598
+ if (sigar->cpu_list_cores) {
599
+ if (log_rollup && (sigar->lcpu > 1)) {
600
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
601
+ "[cpu] treating cores as-is");
602
+ }
603
+ }
604
+ else {
605
+ if (log_rollup && (sigar->lcpu > 1)) {
606
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
607
+ "[cpu] rolling up cores to sockets");
608
+ return 1;
609
+ }
610
+ }
611
+ #endif
612
+ return 0;
613
+ }
614
+
615
+ #define IS_CPU_R(p) \
616
+ ((*p == '(') && (*(p+1) == 'R') && (*(p+2) == ')'))
617
+
618
+ typedef struct {
619
+ char *name; /* search */
620
+ int len;
621
+ char *rname; /* replace */
622
+ int rlen;
623
+ } cpu_model_str_t;
624
+
625
+ /* to later replace 's' with 'r' */
626
+ #define CPU_MODEL_ENT_R(s, r) \
627
+ { s, sizeof(s)-1, r, sizeof(r) }
628
+
629
+ #define CPU_MODEL_ENT(s) \
630
+ CPU_MODEL_ENT_R(s, s)
631
+
632
+ /* after the vendor part of the string is removed,
633
+ * looking for startsWith the entries below
634
+ * to remove the crap after the model name, see
635
+ * ../exp/intel_amd_cpu_models.txt
636
+ */
637
+ static const cpu_model_str_t cpu_models[] = {
638
+ /* intel */
639
+ CPU_MODEL_ENT("Xeon"),
640
+ CPU_MODEL_ENT_R("XEON", "Xeon"),
641
+ CPU_MODEL_ENT("Pentium III"),
642
+ CPU_MODEL_ENT("Pentium II"),
643
+ CPU_MODEL_ENT_R("Pentium(R) III", "Pentium III"),
644
+ CPU_MODEL_ENT_R("Pentium(R) 4", "Pentium 4"),
645
+ CPU_MODEL_ENT_R("Pentium(R) M", "Pentium M"),
646
+ CPU_MODEL_ENT("Pentium Pro"),
647
+ CPU_MODEL_ENT("Celeron"),
648
+
649
+ /* amd */
650
+ CPU_MODEL_ENT("Opteron"),
651
+ CPU_MODEL_ENT("Athlon"),
652
+ CPU_MODEL_ENT("Duron"),
653
+ CPU_MODEL_ENT_R("K6(tm)-III", "K6 III"),
654
+ CPU_MODEL_ENT_R("K6(tm) 3D+", "K6 3D+"),
655
+ { NULL }
656
+ };
657
+
658
+ /* common to win32 and linux */
659
+ void sigar_cpu_model_adjust(sigar_t *sigar, sigar_cpu_info_t *info)
660
+ {
661
+ int len, i;
662
+ char model[128], *ptr=model, *end;
663
+
664
+ memcpy(model, info->model, sizeof(model));
665
+
666
+ /* trim leading and trailing spaces */
667
+ len = strlen(model);
668
+ end = &model[len-1];
669
+ while (*ptr == ' ') ++ptr;
670
+ while (*end == ' ') *end-- = '\0';
671
+
672
+ /* remove vendor from model name */
673
+ len = strlen(info->vendor);
674
+ if (strnEQ(ptr, info->vendor, len)) {
675
+ ptr += len;
676
+ if (IS_CPU_R(ptr)) {
677
+ ptr += 3; /* remove (R) */
678
+ }
679
+ while (*ptr == ' ') ++ptr;
680
+ }
681
+
682
+ if (*ptr == '-') {
683
+ ++ptr; /* e.g. was AMD-K6... */
684
+ }
685
+
686
+ for (i=0; cpu_models[i].name; i++) {
687
+ const cpu_model_str_t *cpu_model = &cpu_models[i];
688
+
689
+ if (strnEQ(ptr, cpu_model->name, cpu_model->len)) {
690
+ memcpy(info->model, cpu_model->rname, cpu_model->rlen);
691
+ return;
692
+ }
693
+ }
694
+
695
+ strcpy(info->model, ptr);
696
+ }
697
+
698
+ /* attempt to derive MHz from model name
699
+ * currently works for certain intel strings
700
+ * see exp/intel_amd_cpu_models.txt
701
+ */
702
+ int sigar_cpu_mhz_from_model(char *model)
703
+ {
704
+ int mhz = SIGAR_FIELD_NOTIMPL;
705
+ char *ptr = model;
706
+
707
+ while (*ptr && (ptr = strchr(ptr, ' '))) {
708
+ while(*ptr && !sigar_isdigit(*ptr)) {
709
+ ptr++;
710
+ }
711
+ mhz = sigar_strtoul(ptr);
712
+
713
+ if (*ptr == '.') {
714
+ /* e.g. "2.40GHz" */
715
+ ++ptr;
716
+ mhz *= 100;
717
+ mhz += sigar_strtoul(ptr);
718
+ break;
719
+ }
720
+ else if (strnEQ(ptr, "GHz", 3) ||
721
+ strnEQ(ptr, "MHz", 3))
722
+ {
723
+ /* e.g. "1500MHz" */
724
+ break;
725
+ }
726
+ else {
727
+ mhz = SIGAR_FIELD_NOTIMPL;
728
+ }
729
+ }
730
+
731
+ if (mhz != SIGAR_FIELD_NOTIMPL) {
732
+ if (strnEQ(ptr, "GHz", 3)) {
733
+ mhz *= 10;
734
+ }
735
+ }
736
+
737
+ return mhz;
738
+ }
739
+
740
+ #if !defined(WIN32) && !defined(NETWARE)
741
+ #include <netdb.h>
742
+ #include <rpc/rpc.h>
743
+ #include <rpc/pmap_prot.h>
744
+ #include <rpc/pmap_clnt.h>
745
+ #ifdef SIGAR_HPUX
746
+ #include <nfs/nfs.h>
747
+ #endif
748
+ #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun) || defined(DARWIN)
749
+ #include <arpa/inet.h>
750
+ #endif
751
+ #if defined(__sun) || defined(SIGAR_HPUX)
752
+ #include <rpc/clnt_soc.h>
753
+ #endif
754
+ #if defined(_AIX) || defined(SIGAR_HPUX) || defined(__OpenBSD__) || defined(__NetBSD__)
755
+ #include <sys/socket.h>
756
+ #endif
757
+
758
+ static enum clnt_stat get_sockaddr(struct sockaddr_in *addr, char *host)
759
+ {
760
+ register struct hostent *hp;
761
+ sigar_hostent_t data;
762
+
763
+ memset(addr, 0, sizeof(struct sockaddr_in));
764
+ addr->sin_family = AF_INET;
765
+
766
+ if ((addr->sin_addr.s_addr = inet_addr(host)) == -1) {
767
+ if (!(hp = sigar_gethostbyname(host, &data))) {
768
+ return RPC_UNKNOWNHOST;
769
+ }
770
+ memcpy(&addr->sin_addr, hp->h_addr, hp->h_length);
771
+ }
772
+
773
+ return RPC_SUCCESS;
774
+ }
775
+
776
+ char *sigar_rpc_strerror(int err)
777
+ {
778
+ return (char *)clnt_sperrno(err);
779
+ }
780
+
781
+ SIGAR_DECLARE(int) sigar_rpc_ping(char *host,
782
+ int protocol,
783
+ unsigned long program,
784
+ unsigned long version)
785
+ {
786
+ CLIENT *client;
787
+ struct sockaddr_in addr;
788
+ int sock;
789
+ struct timeval timeout;
790
+ unsigned short port = 0;
791
+ enum clnt_stat rpc_stat;
792
+
793
+ rpc_stat = get_sockaddr(&addr, host);
794
+ if (rpc_stat != RPC_SUCCESS) {
795
+ return rpc_stat;
796
+ }
797
+
798
+ timeout.tv_sec = 2;
799
+ timeout.tv_usec = 0;
800
+ addr.sin_port = htons(port);
801
+ sock = RPC_ANYSOCK;
802
+
803
+ if (protocol == SIGAR_NETCONN_UDP) {
804
+ client =
805
+ clntudp_create(&addr, program, version,
806
+ timeout, &sock);
807
+ }
808
+ else if (protocol == SIGAR_NETCONN_TCP) {
809
+ client =
810
+ clnttcp_create(&addr, program, version,
811
+ &sock, 0, 0);
812
+ }
813
+ else {
814
+ return RPC_UNKNOWNPROTO;
815
+ }
816
+
817
+ if (!client) {
818
+ return rpc_createerr.cf_stat;
819
+ }
820
+
821
+ timeout.tv_sec = 10;
822
+ timeout.tv_usec = 0;
823
+ rpc_stat = clnt_call(client, NULLPROC, (xdrproc_t)xdr_void, NULL,
824
+ (xdrproc_t)xdr_void, NULL, timeout);
825
+
826
+ clnt_destroy(client);
827
+
828
+ return rpc_stat;
829
+ }
830
+ #endif
831
+
832
+ int sigar_file2str(const char *fname, char *buffer, int buflen)
833
+ {
834
+ int len, status;
835
+ int fd = open(fname, O_RDONLY);
836
+
837
+ if (fd < 0) {
838
+ return ENOENT;
839
+ }
840
+
841
+ if ((len = read(fd, buffer, buflen)) < 0) {
842
+ status = errno;
843
+ }
844
+ else {
845
+ status = SIGAR_OK;
846
+ buffer[len] = '\0';
847
+ }
848
+ close(fd);
849
+
850
+ return status;
851
+ }
852
+
853
+ #ifdef WIN32
854
+ #define vsnprintf _vsnprintf
855
+ #endif
856
+
857
+ #ifdef WIN32
858
+ # define rindex strrchr
859
+ #endif
860
+
861
+ static int proc_module_get_self(void *data, char *name, int len)
862
+ {
863
+ sigar_t *sigar = (sigar_t *)data;
864
+ char *ptr = rindex(name, '/');
865
+
866
+ if (!ptr) {
867
+ return SIGAR_OK;
868
+ }
869
+
870
+ if (strnEQ(ptr+1, "libsigar-", 9)) {
871
+ int offset = ptr - name;
872
+
873
+ sigar->self_path = sigar_strdup(name);
874
+ *(sigar->self_path + offset) = '\0'; /* chop libsigar-*.so */
875
+
876
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
877
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
878
+ "detected sigar-lib='%s'",
879
+ sigar->self_path);
880
+ }
881
+
882
+ return !SIGAR_OK; /* break loop */
883
+ }
884
+
885
+ return SIGAR_OK;
886
+ }
887
+
888
+ char *sigar_get_self_path(sigar_t *sigar)
889
+ {
890
+ if (!sigar->self_path) {
891
+ sigar_proc_modules_t procmods;
892
+ char *self_path = getenv("SIGAR_PATH");
893
+
894
+ if (self_path) {
895
+ sigar->self_path = sigar_strdup(self_path);
896
+ return sigar->self_path;
897
+ }
898
+
899
+ procmods.module_getter = proc_module_get_self;
900
+ procmods.data = sigar;
901
+
902
+ sigar_proc_modules_get(sigar,
903
+ sigar_pid_get(sigar),
904
+ &procmods);
905
+
906
+ if (!sigar->self_path) {
907
+ /* dont try again */
908
+ sigar->self_path = sigar_strdup(".");
909
+ }
910
+ }
911
+
912
+ return sigar->self_path;
913
+ }
914
+
915
+ #ifdef SIGAR_HAS_DLINFO_MODULES
916
+
917
+ static int sigar_dlinfo_get(sigar_t *sigar, const char *func,
918
+ void **handle, Link_map **map)
919
+ {
920
+ Dl_info dli;
921
+
922
+ if (!dladdr((void *)((uintptr_t)sigar_dlinfo_get), &dli)) {
923
+ sigar_log_printf(sigar, SIGAR_LOG_ERROR,
924
+ "[%s] dladdr(%s) = %s",
925
+ func, SIGAR_FUNC, dlerror());
926
+ return ESRCH;
927
+ }
928
+
929
+ if (!(*handle = dlopen(dli.dli_fname, RTLD_LAZY))) {
930
+ sigar_log_printf(sigar, SIGAR_LOG_ERROR,
931
+ "[%s] dlopen(%s) = %s",
932
+ func, dli.dli_fname, dlerror());
933
+ return ESRCH;
934
+ }
935
+
936
+ dlinfo(*handle, RTLD_DI_LINKMAP, map);
937
+
938
+ if (!map) {
939
+ sigar_log_printf(sigar, SIGAR_LOG_ERROR,
940
+ "[%s] dlinfo = %s",
941
+ func, dlerror());
942
+ return ESRCH;
943
+ }
944
+
945
+ return SIGAR_OK;
946
+ }
947
+
948
+ int sigar_dlinfo_modules(sigar_t *sigar, sigar_proc_modules_t *procmods)
949
+ {
950
+ int status;
951
+ void *handle;
952
+ Link_map *map;
953
+
954
+ status = sigar_dlinfo_get(sigar, SIGAR_FUNC, &handle, &map);
955
+ if (status != SIGAR_OK) {
956
+ return status;
957
+ }
958
+
959
+ while (map->l_prev != NULL) {
960
+ map = map->l_prev;
961
+ }
962
+
963
+ do {
964
+ int status =
965
+ procmods->module_getter(procmods->data,
966
+ (char *)map->l_name,
967
+ strlen(map->l_name));
968
+
969
+ if (status != SIGAR_OK) {
970
+ /* not an error; just stop iterating */
971
+ break;
972
+ }
973
+ } while ((map = map->l_next));
974
+
975
+ dlclose(handle);
976
+
977
+ return SIGAR_OK;
978
+ }
979
+ #endif
980
+
981
+ SIGAR_DECLARE(void) sigar_log_printf(sigar_t *sigar, int level,
982
+ const char *format, ...)
983
+ {
984
+ va_list args;
985
+ char buffer[8192];
986
+
987
+ if (level > sigar->log_level) {
988
+ return;
989
+ }
990
+
991
+ if (!sigar->log_impl) {
992
+ return;
993
+ }
994
+
995
+ va_start(args, format);
996
+ vsnprintf(buffer, sizeof(buffer), format, args);
997
+ va_end(args);
998
+
999
+ sigar->log_impl(sigar, sigar->log_data, level, buffer);
1000
+ }
1001
+
1002
+ SIGAR_DECLARE(void) sigar_log(sigar_t *sigar, int level, char *message)
1003
+ {
1004
+ if (level > sigar->log_level) {
1005
+ return;
1006
+ }
1007
+
1008
+ if (!sigar->log_impl) {
1009
+ return;
1010
+ }
1011
+
1012
+ sigar->log_impl(sigar, sigar->log_data, level, message);
1013
+ }
1014
+
1015
+ SIGAR_DECLARE(void) sigar_log_impl_set(sigar_t *sigar, void *data,
1016
+ sigar_log_impl_t impl)
1017
+ {
1018
+ sigar->log_data = data;
1019
+ sigar->log_impl = impl;
1020
+ }
1021
+
1022
+ SIGAR_DECLARE(int) sigar_log_level_get(sigar_t *sigar)
1023
+ {
1024
+ return sigar->log_level;
1025
+ }
1026
+
1027
+ static const char *log_levels[] = {
1028
+ "FATAL",
1029
+ "ERROR",
1030
+ "WARN",
1031
+ "INFO",
1032
+ "DEBUG",
1033
+ "TRACE"
1034
+ };
1035
+
1036
+ SIGAR_DECLARE(const char *) sigar_log_level_string_get(sigar_t *sigar)
1037
+ {
1038
+ return log_levels[sigar->log_level];
1039
+ }
1040
+
1041
+ SIGAR_DECLARE(void) sigar_log_level_set(sigar_t *sigar, int level)
1042
+ {
1043
+ sigar->log_level = level;
1044
+ }
1045
+
1046
+ SIGAR_DECLARE(void) sigar_log_impl_file(sigar_t *sigar, void *data,
1047
+ int level, char *message)
1048
+ {
1049
+ FILE *fp = (FILE*)data;
1050
+ fprintf(fp, "[%s] %s\n", log_levels[level], message);
1051
+ }
1052
+
1053
+ #ifndef WIN32
1054
+ sigar_int64_t sigar_time_now_millis(void)
1055
+ {
1056
+ struct timeval tv;
1057
+ gettimeofday(&tv, NULL);
1058
+ return ((tv.tv_sec * SIGAR_USEC) + tv.tv_usec) / SIGAR_MSEC;
1059
+ }
1060
+ #endif