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