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,181 @@
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
+ #include <stdio.h>
23
+ /*
24
+ * hash table to cache values where key is a unique number
25
+ * such as:
26
+ * pid -> some process data
27
+ * uid -> user name
28
+ * gid -> group name
29
+ */
30
+
31
+ #define ENTRIES_SIZE(n) \
32
+ (sizeof(sigar_cache_entry_t *) * (n))
33
+
34
+ /* wrap free() for use w/ dmalloc */
35
+ static void free_value(void *ptr)
36
+ {
37
+ free(ptr);
38
+ }
39
+
40
+ sigar_cache_t *sigar_cache_new(int size)
41
+ {
42
+ sigar_cache_t *table = malloc(sizeof(*table));
43
+ table->count = 0;
44
+ table->size = size;
45
+ table->entries = malloc(ENTRIES_SIZE(size));
46
+ memset(table->entries, '\0', ENTRIES_SIZE(size));
47
+ table->free_value = free_value;
48
+ return table;
49
+ }
50
+
51
+ #ifdef DEBUG_CACHE
52
+ /* see how well entries are distributed */
53
+ static void sigar_cache_dump(sigar_cache_t *table)
54
+ {
55
+ int i;
56
+ sigar_cache_entry_t **entries = table->entries;
57
+
58
+ for (i=0; i<table->size; i++) {
59
+ sigar_cache_entry_t *entry = *entries++;
60
+
61
+ printf("|");
62
+ while (entry) {
63
+ printf("%lld", entry->id);
64
+ if (entry->next) {
65
+ printf(",");
66
+ }
67
+ entry = entry->next;
68
+ }
69
+ }
70
+ printf("\n");
71
+ fflush(stdout);
72
+ }
73
+ #endif
74
+
75
+ static void sigar_cache_rehash(sigar_cache_t *table)
76
+ {
77
+ int i;
78
+ unsigned int new_size = table->size * 2 + 1;
79
+ sigar_cache_entry_t **entries = table->entries;
80
+ sigar_cache_entry_t **new_entries =
81
+ malloc(ENTRIES_SIZE(new_size));
82
+
83
+ memset(new_entries, '\0', ENTRIES_SIZE(new_size));
84
+
85
+ for (i=0; i<table->size; i++) {
86
+ sigar_cache_entry_t *entry = *entries++;
87
+
88
+ while (entry) {
89
+ sigar_cache_entry_t *next = entry->next;
90
+ sigar_uint64_t hash = entry->id % new_size;
91
+
92
+ entry->next = new_entries[hash];
93
+ new_entries[hash] = entry;
94
+ entry = next;
95
+ }
96
+ }
97
+
98
+ free(table->entries);
99
+ table->entries = new_entries;
100
+ table->size = new_size;
101
+ }
102
+
103
+ #define SIGAR_CACHE_IX(t, k) \
104
+ t->entries + (k % t->size)
105
+
106
+ sigar_cache_entry_t *sigar_cache_find(sigar_cache_t *table,
107
+ sigar_uint64_t key)
108
+ {
109
+ sigar_cache_entry_t *entry, **ptr;
110
+
111
+ for (ptr = SIGAR_CACHE_IX(table, key), entry = *ptr;
112
+ entry;
113
+ ptr = &entry->next, entry = *ptr)
114
+ {
115
+ if (entry->id == key) {
116
+ return entry;
117
+ }
118
+ }
119
+
120
+ return NULL;
121
+ }
122
+
123
+ /* create entry if it does not exist */
124
+ sigar_cache_entry_t *sigar_cache_get(sigar_cache_t *table,
125
+ sigar_uint64_t key)
126
+ {
127
+ sigar_cache_entry_t *entry, **ptr;
128
+
129
+ for (ptr = SIGAR_CACHE_IX(table, key), entry = *ptr;
130
+ entry;
131
+ ptr = &entry->next, entry = *ptr)
132
+ {
133
+ if (entry->id == key) {
134
+ return entry;
135
+ }
136
+ }
137
+
138
+ if (table->count++ > table->size) {
139
+ sigar_cache_rehash(table);
140
+
141
+ for (ptr = SIGAR_CACHE_IX(table, key), entry = *ptr;
142
+ entry;
143
+ ptr = &entry->next, entry = *ptr)
144
+ {
145
+ }
146
+ }
147
+
148
+ *ptr = entry = malloc(sizeof(*entry));
149
+ entry->id = key;
150
+ entry->value = NULL;
151
+ entry->next = NULL;
152
+
153
+ return entry;
154
+ }
155
+
156
+ void sigar_cache_destroy(sigar_cache_t *table)
157
+ {
158
+ int i;
159
+ sigar_cache_entry_t **entries = table->entries;
160
+
161
+ #ifdef DEBUG_CACHE
162
+ sigar_cache_dump(table);
163
+ #endif
164
+
165
+ for (i=0; i<table->size; i++) {
166
+ sigar_cache_entry_t *entry, *ptr;
167
+ entry = *entries++;
168
+
169
+ while (entry) {
170
+ if (entry->value) {
171
+ table->free_value(entry->value);
172
+ }
173
+ ptr = entry->next;
174
+ free(entry);
175
+ entry = ptr;
176
+ }
177
+ }
178
+
179
+ free(table->entries);
180
+ free(table);
181
+ }
@@ -0,0 +1,792 @@
1
+ /* ====================================================================
2
+ * The Apache Software License, Version 1.1
3
+ *
4
+ * Copyright (c) 2000-2003 The Apache Software Foundation. All rights
5
+ * reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions
9
+ * are met:
10
+ *
11
+ * 1. Redistributions of source code must retain the above copyright
12
+ * notice, this list of conditions and the following disclaimer.
13
+ *
14
+ * 2. Redistributions in binary form must reproduce the above copyright
15
+ * notice, this list of conditions and the following disclaimer in
16
+ * the documentation and/or other materials provided with the
17
+ * distribution.
18
+ *
19
+ * 3. The end-user documentation included with the redistribution,
20
+ * if any, must include the following acknowledgment:
21
+ * "This product includes software developed by the
22
+ * Apache Software Foundation (http://www.apache.org/)."
23
+ * Alternately, this acknowledgment may appear in the software itself,
24
+ * if and wherever such third-party acknowledgments normally appear.
25
+ *
26
+ * 4. The names "Apache" and "Apache Software Foundation" must
27
+ * not be used to endorse or promote products derived from this
28
+ * software without prior written permission. For written
29
+ * permission, please contact apache@apache.org.
30
+ *
31
+ * 5. Products derived from this software may not be called "Apache",
32
+ * nor may "Apache" appear in their name, without prior written
33
+ * permission of the Apache Software Foundation.
34
+ *
35
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46
+ * SUCH DAMAGE.
47
+ * ====================================================================
48
+ *
49
+ * This software consists of voluntary contributions made by many
50
+ * individuals on behalf of the Apache Software Foundation. For more
51
+ * information on the Apache Software Foundation, please see
52
+ * <http://www.apache.org/>.
53
+ */
54
+
55
+ #ifndef WIN32
56
+ # ifdef _AIX
57
+ # define _LARGE_FILES
58
+ # else
59
+ # define _FILE_OFFSET_BITS 64
60
+ # define _LARGEFILE64_SOURCE
61
+ # endif
62
+ #endif
63
+
64
+ #include "sigar.h"
65
+
66
+ #ifndef WIN32
67
+ #if defined(__FreeBSD__) || defined(__OpenBSD__)
68
+ # include <sys/param.h>
69
+ # include <sys/mount.h>
70
+ #else
71
+ # include <sys/statvfs.h>
72
+ # define HAVE_STATVFS
73
+ #endif
74
+ #include <errno.h>
75
+
76
+ #define SIGAR_FS_BLOCKS_TO_BYTES(val, bsize) ((val * bsize) >> 1)
77
+
78
+ int sigar_statvfs(sigar_t *sigar,
79
+ const char *dirname,
80
+ sigar_file_system_usage_t *fsusage)
81
+ {
82
+ sigar_uint64_t val, bsize;
83
+ #ifdef HAVE_STATVFS
84
+ struct statvfs buf;
85
+ int status =
86
+ # if defined(__sun) && !defined(_LP64)
87
+ /* http://bugs.opensolaris.org/view_bug.do?bug_id=4462986 */
88
+ statvfs(dirname, (void *)&buf);
89
+ # else
90
+ statvfs(dirname, &buf);
91
+ # endif
92
+ #else
93
+ struct statfs buf;
94
+ int status = statfs(dirname, &buf);
95
+ #endif
96
+
97
+ if (status != 0) {
98
+ return errno;
99
+ }
100
+
101
+ #ifdef HAVE_STATVFS
102
+ bsize = buf.f_frsize / 512;
103
+ #else
104
+ bsize = buf.f_bsize / 512;
105
+ #endif
106
+ val = buf.f_blocks;
107
+ fsusage->total = SIGAR_FS_BLOCKS_TO_BYTES(val, bsize);
108
+ val = buf.f_bfree;
109
+ fsusage->free = SIGAR_FS_BLOCKS_TO_BYTES(val, bsize);
110
+ val = buf.f_bavail;
111
+ fsusage->avail = SIGAR_FS_BLOCKS_TO_BYTES(val, bsize);
112
+ fsusage->used = fsusage->total - fsusage->free;
113
+ fsusage->files = buf.f_files;
114
+ fsusage->free_files = buf.f_ffree;
115
+
116
+ return SIGAR_OK;
117
+ }
118
+ #endif
119
+
120
+ /*
121
+ * whittled down version of apr/file_info/{unix,win32}/filestat.c
122
+ * to fillin sigar_fileattrs_t
123
+ */
124
+ #include "sigar_fileinfo.h"
125
+ #include "sigar_log.h"
126
+
127
+ #ifndef SIGAR_ZERO
128
+ #define SIGAR_ZERO(s) \
129
+ memset(s, '\0', sizeof(*(s)))
130
+ #endif
131
+
132
+ #ifdef WIN32
133
+ #include <windows.h>
134
+ sigar_uint64_t sigar_FileTimeToTime(FILETIME *ft);
135
+ #else
136
+ #include <string.h>
137
+ #endif
138
+
139
+ static const char* types[] = {
140
+ "none",
141
+ "regular",
142
+ "directory",
143
+ "character device",
144
+ "block device",
145
+ "pipe",
146
+ "symbolic link",
147
+ "socket",
148
+ "unknown"
149
+ };
150
+
151
+ SIGAR_DECLARE(const char *)
152
+ sigar_file_attrs_type_string_get(sigar_file_type_e type)
153
+ {
154
+ if ((type < SIGAR_FILETYPE_NOFILE) ||
155
+ (type > SIGAR_FILETYPE_UNKFILE))
156
+ {
157
+ type = SIGAR_FILETYPE_UNKFILE;
158
+ }
159
+
160
+ return types[type];
161
+ }
162
+
163
+ static const sigar_uint64_t perm_modes[] = {
164
+ SIGAR_UREAD, SIGAR_UWRITE, SIGAR_UEXECUTE,
165
+ SIGAR_GREAD, SIGAR_GWRITE, SIGAR_GEXECUTE,
166
+ SIGAR_WREAD, SIGAR_WWRITE, SIGAR_WEXECUTE
167
+ };
168
+
169
+ static const char perm_chars[] = "rwx";
170
+
171
+ SIGAR_DECLARE(char *)
172
+ sigar_file_attrs_permissions_string_get(sigar_uint64_t permissions,
173
+ char *str)
174
+ {
175
+ char *ptr = str;
176
+ int i=0, j=0;
177
+
178
+ for (i=0; i<9; i+=3) {
179
+ for (j=0; j<3; j++) {
180
+ if (permissions & perm_modes[i+j]) {
181
+ *ptr = perm_chars[j];
182
+ }
183
+ else {
184
+ *ptr = '-';
185
+ }
186
+ ptr++;
187
+ }
188
+ }
189
+
190
+ *ptr = '\0';
191
+ return str;
192
+ }
193
+
194
+ static const int perm_int[] = {
195
+ 400, 200, 100,
196
+ 40, 20, 10,
197
+ 4, 2, 1
198
+ };
199
+
200
+ SIGAR_DECLARE(int)sigar_file_attrs_mode_get(sigar_uint64_t permissions)
201
+ {
202
+ int i=0;
203
+ int perms = 0;
204
+
205
+ /* no doubt there is some fancy bitshifting
206
+ * to convert, but this works fine.
207
+ */
208
+ for (i=0; i<9; i++) {
209
+ if (permissions & perm_modes[i]) {
210
+ perms += perm_int[i];
211
+ }
212
+ }
213
+
214
+ return perms;
215
+ }
216
+
217
+ #define IS_DOTDIR(dir) \
218
+ ((dir[0] == '.') && (!dir[1] || ((dir[1] == '.') && !dir[2])))
219
+
220
+ #define DIR_STAT_WARN() \
221
+ sigar_log_printf(sigar, SIGAR_LOG_WARN, \
222
+ "dir_stat: cannot stat `%s': %s", \
223
+ name, \
224
+ sigar_strerror(sigar, status))
225
+
226
+ #if defined(NETWARE)
227
+
228
+ int sigar_dir_stat_get(sigar_t *sigar,
229
+ const char *dir,
230
+ sigar_dir_stat_t *dirstats)
231
+ {
232
+ return SIGAR_ENOTIMPL;
233
+ }
234
+
235
+ int sigar_file_attrs_get(sigar_t *sigar,
236
+ const char *file,
237
+ sigar_file_attrs_t *fileattrs)
238
+ {
239
+ return SIGAR_ENOTIMPL;
240
+ }
241
+
242
+ int sigar_link_attrs_get(sigar_t *sigar,
243
+ const char *file,
244
+ sigar_file_attrs_t *fileattrs)
245
+ {
246
+ return SIGAR_ENOTIMPL;
247
+ }
248
+
249
+ #elif defined(WIN32)
250
+
251
+ #include <accctrl.h>
252
+ #include <aclapi.h>
253
+
254
+ static void fillin_fileattrs(sigar_file_attrs_t *finfo,
255
+ WIN32_FILE_ATTRIBUTE_DATA *wininfo,
256
+ int linkinfo)
257
+ {
258
+ DWORD *sizes = &wininfo->nFileSizeHigh;
259
+
260
+ finfo->atime = sigar_FileTimeToTime(&wininfo->ftLastAccessTime) / 1000;
261
+ finfo->ctime = sigar_FileTimeToTime(&wininfo->ftCreationTime) / 1000;
262
+ finfo->mtime = sigar_FileTimeToTime(&wininfo->ftLastWriteTime) / 1000;
263
+
264
+ finfo->size =
265
+ (sigar_uint64_t)sizes[1] | ((sigar_uint64_t)sizes[0] << 32);
266
+
267
+ if (linkinfo &&
268
+ (wininfo->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
269
+ finfo->type = SIGAR_FILETYPE_LNK;
270
+ }
271
+ else if (wininfo->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
272
+ finfo->type = SIGAR_FILETYPE_DIR;
273
+ }
274
+ else {
275
+ finfo->type = SIGAR_FILETYPE_REG;
276
+ }
277
+ }
278
+
279
+ static sigar_uint64_t convert_perms(ACCESS_MASK acc, sigar_uint64_t scope)
280
+ {
281
+ sigar_uint64_t perms = 0;
282
+ if (acc & FILE_EXECUTE) {
283
+ perms |= SIGAR_WEXECUTE;
284
+ }
285
+ if (acc & FILE_WRITE_DATA) {
286
+ perms |= SIGAR_WWRITE;
287
+ }
288
+ if (acc & FILE_READ_DATA) {
289
+ perms |= SIGAR_WREAD;
290
+ }
291
+
292
+ return (perms << scope);
293
+ }
294
+
295
+ static int get_security_info(sigar_t *sigar,
296
+ const char *file,
297
+ sigar_file_attrs_t *fileattrs)
298
+ {
299
+ DWORD retval;
300
+ PSID user = NULL, group = NULL, world = NULL;
301
+ PACL dacl = NULL;
302
+ PSECURITY_DESCRIPTOR pdesc = NULL;
303
+ SECURITY_INFORMATION sinfo =
304
+ OWNER_SECURITY_INFORMATION |
305
+ GROUP_SECURITY_INFORMATION |
306
+ DACL_SECURITY_INFORMATION;
307
+ TRUSTEE ident = {NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID};
308
+ ACCESS_MASK acc;
309
+ SID_IDENTIFIER_AUTHORITY auth = SECURITY_WORLD_SID_AUTHORITY;
310
+
311
+ retval = GetNamedSecurityInfo((char *)file,
312
+ SE_FILE_OBJECT,
313
+ sinfo,
314
+ &user,
315
+ &group,
316
+ &dacl,
317
+ NULL,
318
+ &pdesc);
319
+
320
+ if (retval != ERROR_SUCCESS) {
321
+ return retval;
322
+ }
323
+
324
+ if (!AllocateAndInitializeSid(&auth, 1, SECURITY_WORLD_RID,
325
+ 0, 0, 0, 0, 0, 0, 0, &world))
326
+ {
327
+ world = NULL;
328
+ }
329
+
330
+ ident.TrusteeType = TRUSTEE_IS_USER;
331
+ ident.ptstrName = user;
332
+ if (GetEffectiveRightsFromAcl(dacl, &ident, &acc) == ERROR_SUCCESS) {
333
+ fileattrs->permissions |= convert_perms(acc, 8);
334
+ }
335
+
336
+ ident.TrusteeType = TRUSTEE_IS_GROUP;
337
+ ident.ptstrName = group;
338
+ if (GetEffectiveRightsFromAcl(dacl, &ident, &acc) == ERROR_SUCCESS) {
339
+ fileattrs->permissions |= convert_perms(acc, 4);
340
+ }
341
+
342
+ if (world) {
343
+ ident.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
344
+ ident.ptstrName = world;
345
+ if (GetEffectiveRightsFromAcl(dacl, &ident, &acc) == ERROR_SUCCESS) {
346
+ fileattrs->permissions |= convert_perms(acc, 0);
347
+ }
348
+ }
349
+
350
+ if (world) {
351
+ FreeSid(world);
352
+ }
353
+
354
+ LocalFree(pdesc);
355
+
356
+ return SIGAR_OK;
357
+ }
358
+
359
+ static int fileattrs_get(sigar_t *sigar,
360
+ const char *file,
361
+ sigar_file_attrs_t *fileattrs,
362
+ int linkinfo)
363
+ {
364
+ BY_HANDLE_FILE_INFORMATION info;
365
+ WIN32_FILE_ATTRIBUTE_DATA attrs;
366
+ HANDLE handle;
367
+ DWORD flags;
368
+
369
+ SIGAR_ZERO(fileattrs);
370
+
371
+ if (!GetFileAttributesExA(file,
372
+ GetFileExInfoStandard,
373
+ &attrs))
374
+ {
375
+ return GetLastError();
376
+ }
377
+
378
+ fillin_fileattrs(fileattrs, &attrs, linkinfo);
379
+
380
+ flags = fileattrs->type == SIGAR_FILETYPE_DIR ?
381
+ FILE_FLAG_BACKUP_SEMANTICS :
382
+ FILE_ATTRIBUTE_NORMAL;
383
+
384
+ handle = CreateFile(file,
385
+ GENERIC_READ,
386
+ FILE_SHARE_READ,
387
+ NULL,
388
+ OPEN_EXISTING,
389
+ flags,
390
+ NULL);
391
+
392
+ if (handle != INVALID_HANDLE_VALUE) {
393
+ if (GetFileInformationByHandle(handle, &info)) {
394
+ fileattrs->inode =
395
+ info.nFileIndexLow |
396
+ (info.nFileIndexHigh << 32);
397
+ fileattrs->device = info.dwVolumeSerialNumber;
398
+ fileattrs->nlink = info.nNumberOfLinks;
399
+ }
400
+ CloseHandle(handle);
401
+ }
402
+
403
+ get_security_info(sigar, file, fileattrs);
404
+
405
+ return SIGAR_OK;
406
+ }
407
+
408
+ SIGAR_DECLARE(int) sigar_file_attrs_get(sigar_t *sigar,
409
+ const char *file,
410
+ sigar_file_attrs_t *fileattrs)
411
+ {
412
+ return fileattrs_get(sigar, file, fileattrs, 0);
413
+ }
414
+
415
+ SIGAR_DECLARE(int) sigar_link_attrs_get(sigar_t *sigar,
416
+ const char *file,
417
+ sigar_file_attrs_t *fileattrs)
418
+ {
419
+ return fileattrs_get(sigar, file, fileattrs, 1);
420
+ }
421
+
422
+ static __inline int file_type(char *file)
423
+ {
424
+ WIN32_FILE_ATTRIBUTE_DATA attrs;
425
+
426
+ if (!GetFileAttributesExA(file,
427
+ GetFileExInfoStandard,
428
+ &attrs))
429
+ {
430
+ return -1;
431
+ }
432
+
433
+ if (attrs.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
434
+ return SIGAR_FILETYPE_LNK;
435
+ }
436
+ else if (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
437
+ return SIGAR_FILETYPE_DIR;
438
+ }
439
+ else {
440
+ return SIGAR_FILETYPE_REG;
441
+ }
442
+ }
443
+
444
+ static int dir_stat_get(sigar_t *sigar,
445
+ const char *dir,
446
+ sigar_dir_stat_t *dirstats,
447
+ int recurse)
448
+ {
449
+ int status;
450
+ char name[SIGAR_PATH_MAX+1];
451
+ int len = strlen(dir);
452
+ int max = sizeof(name)-len-1;
453
+ char *ptr = name;
454
+ WIN32_FIND_DATA data;
455
+ HANDLE handle;
456
+ DWORD error;
457
+ char delim;
458
+
459
+ if (file_type((char *)dir) != SIGAR_FILETYPE_DIR) {
460
+ return ERROR_NO_MORE_FILES;
461
+ }
462
+
463
+ strncpy(name, dir, sizeof(name));
464
+ ptr += len;
465
+ if (strchr(dir, '/')) {
466
+ delim = '/';
467
+ }
468
+ else {
469
+ delim = '\\';
470
+ }
471
+ if (name[len] != delim) {
472
+ *ptr++ = delim;
473
+ len++;
474
+ max--;
475
+ }
476
+
477
+ /* e.g. "C:\sigar\*" */
478
+ name[len] = '*';
479
+ name[len+1] = '\0';
480
+
481
+ handle = FindFirstFile(name, &data);
482
+ if (handle == INVALID_HANDLE_VALUE) {
483
+ return GetLastError();
484
+ }
485
+
486
+ do {
487
+ /* skip '.' and '..' */
488
+ if (IS_DOTDIR(data.cFileName)) {
489
+ continue;
490
+ }
491
+
492
+ dirstats->disk_usage +=
493
+ (data.nFileSizeHigh * (MAXDWORD+1)) +
494
+ data.nFileSizeLow;
495
+
496
+ /* e.g. "C:\sigar\lib" */
497
+ strncpy(ptr, data.cFileName, max);
498
+ ptr[max] = '\0';
499
+
500
+ switch (file_type(name)) {
501
+ case -1:
502
+ break;
503
+ case SIGAR_FILETYPE_REG:
504
+ ++dirstats->files;
505
+ break;
506
+ case SIGAR_FILETYPE_DIR:
507
+ ++dirstats->subdirs;
508
+ if (recurse) {
509
+ status =
510
+ dir_stat_get(sigar, name,
511
+ dirstats, recurse);
512
+ if (status != SIGAR_OK) {
513
+ DIR_STAT_WARN();
514
+ }
515
+ }
516
+ break;
517
+ case SIGAR_FILETYPE_LNK:
518
+ ++dirstats->symlinks;
519
+ break;
520
+ case SIGAR_FILETYPE_CHR:
521
+ ++dirstats->chrdevs;
522
+ break;
523
+ case SIGAR_FILETYPE_BLK:
524
+ ++dirstats->blkdevs;
525
+ break;
526
+ case SIGAR_FILETYPE_SOCK:
527
+ ++dirstats->sockets;
528
+ break;
529
+ default:
530
+ ++dirstats->total;
531
+ }
532
+ } while (FindNextFile(handle, &data));
533
+
534
+ error = GetLastError();
535
+
536
+ FindClose(handle);
537
+
538
+ if (error != ERROR_NO_MORE_FILES) {
539
+ return error;
540
+ }
541
+
542
+ dirstats->total =
543
+ dirstats->files +
544
+ dirstats->subdirs +
545
+ dirstats->symlinks +
546
+ dirstats->chrdevs +
547
+ dirstats->blkdevs +
548
+ dirstats->sockets;
549
+
550
+ return SIGAR_OK;
551
+ }
552
+
553
+ #else
554
+
555
+ #include <dirent.h>
556
+ #include <errno.h>
557
+ #include <sys/stat.h>
558
+ #include <sys/types.h>
559
+
560
+ static sigar_file_type_e filetype_from_mode(mode_t mode)
561
+ {
562
+ sigar_file_type_e type;
563
+
564
+ switch (mode & S_IFMT) {
565
+ case S_IFREG:
566
+ type = SIGAR_FILETYPE_REG; break;
567
+ case S_IFDIR:
568
+ type = SIGAR_FILETYPE_DIR; break;
569
+ case S_IFLNK:
570
+ type = SIGAR_FILETYPE_LNK; break;
571
+ case S_IFCHR:
572
+ type = SIGAR_FILETYPE_CHR; break;
573
+ case S_IFBLK:
574
+ type = SIGAR_FILETYPE_BLK; break;
575
+ #if defined(S_IFFIFO)
576
+ case S_IFFIFO:
577
+ type = SIGAR_FILETYPE_PIPE; break;
578
+ #endif
579
+ #if !defined(BEOS) && defined(S_IFSOCK)
580
+ case S_IFSOCK:
581
+ type = SIGAR_FILETYPE_SOCK; break;
582
+ #endif
583
+
584
+ default:
585
+ /* Work around missing S_IFxxx values above
586
+ * for Linux et al.
587
+ */
588
+ #if !defined(S_IFFIFO) && defined(S_ISFIFO)
589
+ if (S_ISFIFO(mode)) {
590
+ type = SIGAR_FILETYPE_PIPE;
591
+ } else
592
+ #endif
593
+ #if !defined(BEOS) && !defined(S_IFSOCK) && defined(S_ISSOCK)
594
+ if (S_ISSOCK(mode)) {
595
+ type = SIGAR_FILETYPE_SOCK;
596
+ } else
597
+ #endif
598
+ type = SIGAR_FILETYPE_UNKFILE;
599
+ }
600
+ return type;
601
+ }
602
+
603
+ static sigar_uint64_t sigar_unix_mode2perms(mode_t mode)
604
+ {
605
+ sigar_uint64_t perms = 0;
606
+
607
+ if (mode & S_IRUSR)
608
+ perms |= SIGAR_UREAD;
609
+ if (mode & S_IWUSR)
610
+ perms |= SIGAR_UWRITE;
611
+ if (mode & S_IXUSR)
612
+ perms |= SIGAR_UEXECUTE;
613
+
614
+ if (mode & S_IRGRP)
615
+ perms |= SIGAR_GREAD;
616
+ if (mode & S_IWGRP)
617
+ perms |= SIGAR_GWRITE;
618
+ if (mode & S_IXGRP)
619
+ perms |= SIGAR_GEXECUTE;
620
+
621
+ if (mode & S_IROTH)
622
+ perms |= SIGAR_WREAD;
623
+ if (mode & S_IWOTH)
624
+ perms |= SIGAR_WWRITE;
625
+ if (mode & S_IXOTH)
626
+ perms |= SIGAR_WEXECUTE;
627
+
628
+ return perms;
629
+ }
630
+
631
+ static void copy_stat_info(sigar_file_attrs_t *fileattrs,
632
+ struct stat *info)
633
+ {
634
+ fileattrs->permissions = sigar_unix_mode2perms(info->st_mode);
635
+ fileattrs->type = filetype_from_mode(info->st_mode);
636
+ fileattrs->uid = info->st_uid;
637
+ fileattrs->gid = info->st_gid;
638
+ fileattrs->size = info->st_size;
639
+ fileattrs->inode = info->st_ino;
640
+ fileattrs->device = info->st_dev;
641
+ fileattrs->nlink = info->st_nlink;
642
+ fileattrs->atime = info->st_atime;
643
+ fileattrs->mtime = info->st_mtime;
644
+ fileattrs->ctime = info->st_ctime;
645
+ fileattrs->atime *= 1000;
646
+ fileattrs->mtime *= 1000;
647
+ fileattrs->ctime *= 1000;
648
+ }
649
+
650
+ int sigar_file_attrs_get(sigar_t *sigar,
651
+ const char *file,
652
+ sigar_file_attrs_t *fileattrs)
653
+ {
654
+ struct stat info;
655
+
656
+ if (stat(file, &info) == 0) {
657
+ copy_stat_info(fileattrs, &info);
658
+ return SIGAR_OK;
659
+ }
660
+ else {
661
+ return errno;
662
+ }
663
+ }
664
+
665
+ int sigar_link_attrs_get(sigar_t *sigar,
666
+ const char *file,
667
+ sigar_file_attrs_t *fileattrs)
668
+ {
669
+ struct stat info;
670
+
671
+ if (lstat(file, &info) == 0) {
672
+ copy_stat_info(fileattrs, &info);
673
+ return SIGAR_OK;
674
+ }
675
+ else {
676
+ return errno;
677
+ }
678
+ }
679
+
680
+ static int dir_stat_get(sigar_t *sigar,
681
+ const char *dir,
682
+ sigar_dir_stat_t *dirstats,
683
+ int recurse)
684
+ {
685
+ int status;
686
+ char name[SIGAR_PATH_MAX+1];
687
+ int len = strlen(dir);
688
+ int max = sizeof(name)-len-1;
689
+ char *ptr = name;
690
+ DIR *dirp = opendir(dir);
691
+ struct dirent *ent;
692
+ struct stat info;
693
+ #ifdef HAVE_READDIR_R
694
+ struct dirent dbuf;
695
+ #endif
696
+
697
+ if (!dirp) {
698
+ return errno;
699
+ }
700
+
701
+ strncpy(name, dir, sizeof(name));
702
+ ptr += len;
703
+ if (name[len] != '/') {
704
+ *ptr++ = '/';
705
+ len++;
706
+ max--;
707
+ }
708
+
709
+ #ifdef HAVE_READDIR_R
710
+ while (readdir_r(dirp, &dbuf, &ent) == 0) {
711
+ if (ent == NULL) {
712
+ break;
713
+ }
714
+ #else
715
+ while ((ent = readdir(dirp))) {
716
+ #endif
717
+ /* skip '.' and '..' */
718
+ if (IS_DOTDIR(ent->d_name)) {
719
+ continue;
720
+ }
721
+
722
+ strncpy(ptr, ent->d_name, max);
723
+ ptr[max] = '\0';
724
+
725
+ if (lstat(name, &info) != 0) {
726
+ continue;
727
+ }
728
+
729
+ dirstats->disk_usage += info.st_size;
730
+
731
+ switch (filetype_from_mode(info.st_mode)) {
732
+ case SIGAR_FILETYPE_REG:
733
+ ++dirstats->files;
734
+ break;
735
+ case SIGAR_FILETYPE_DIR:
736
+ ++dirstats->subdirs;
737
+ if (recurse) {
738
+ status =
739
+ dir_stat_get(sigar, name,
740
+ dirstats, recurse);
741
+ if (status != SIGAR_OK) {
742
+ DIR_STAT_WARN();
743
+ }
744
+ }
745
+ break;
746
+ case SIGAR_FILETYPE_LNK:
747
+ ++dirstats->symlinks;
748
+ break;
749
+ case SIGAR_FILETYPE_CHR:
750
+ ++dirstats->chrdevs;
751
+ break;
752
+ case SIGAR_FILETYPE_BLK:
753
+ ++dirstats->blkdevs;
754
+ break;
755
+ case SIGAR_FILETYPE_SOCK:
756
+ ++dirstats->sockets;
757
+ break;
758
+ default:
759
+ ++dirstats->total;
760
+ }
761
+ }
762
+
763
+ dirstats->total =
764
+ dirstats->files +
765
+ dirstats->subdirs +
766
+ dirstats->symlinks +
767
+ dirstats->chrdevs +
768
+ dirstats->blkdevs +
769
+ dirstats->sockets;
770
+
771
+ closedir(dirp);
772
+
773
+ return SIGAR_OK;
774
+ }
775
+
776
+ #endif
777
+
778
+ SIGAR_DECLARE(int) sigar_dir_stat_get(sigar_t *sigar,
779
+ const char *dir,
780
+ sigar_dir_stat_t *dirstats)
781
+ {
782
+ SIGAR_ZERO(dirstats);
783
+ return dir_stat_get(sigar, dir, dirstats, 0);
784
+ }
785
+
786
+ SIGAR_DECLARE(int) sigar_dir_usage_get(sigar_t *sigar,
787
+ const char *dir,
788
+ sigar_dir_usage_t *dirusage)
789
+ {
790
+ SIGAR_ZERO(dirusage);
791
+ return dir_stat_get(sigar, dir, dirusage, 1);
792
+ }