sigar 0.7.0 → 0.7.1

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