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#include "sigar_private.h" 95#include "sigar_util.h" 96 97#define SIGAR_FS_BLOCKS_TO_BYTES(val, bsize) ((val * bsize) >> 1) 98 99int sigar_statvfs(sigar_t *sigar, 100 const char *dirname, 101 sigar_file_system_usage_t *fsusage) 102{ 103 sigar_uint64_t val, bsize; 104#ifdef HAVE_STATVFS 105 struct statvfs buf; 106 int status = 107# if defined(__sun) && !defined(_LP64) 108 /* http://bugs.opensolaris.org/view_bug.do?bug_id=4462986 */ 109 statvfs(dirname, (void *)&buf); 110# else 111 statvfs(dirname, &buf); 112# endif 113#else 114 struct statfs buf; 115 int status = statfs(dirname, &buf); 116#endif 117 118 if (status != 0) { 119 return errno; 120 } 121 122#ifdef HAVE_STATVFS 123 bsize = buf.f_frsize / 512; 124#else 125 bsize = buf.f_bsize / 512; 126#endif 127 val = buf.f_blocks; 128 fsusage->total = SIGAR_FS_BLOCKS_TO_BYTES(val, bsize); 129 val = buf.f_bfree; 130 fsusage->free = SIGAR_FS_BLOCKS_TO_BYTES(val, bsize); 131 val = buf.f_bavail; 132 fsusage->avail = SIGAR_FS_BLOCKS_TO_BYTES(val, bsize); 133 fsusage->used = fsusage->total - fsusage->free; 134 fsusage->files = buf.f_files; 135 fsusage->free_files = buf.f_ffree; 136 137 return SIGAR_OK; 138} 139#endif 140 141/* 142 * whittled down version of apr/file_info/{unix,win32}/filestat.c 143 * to fillin sigar_fileattrs_t 144 */ 145#include "sigar_fileinfo.h" 146#include "sigar_log.h" 147 148#ifndef SIGAR_ZERO 149#define SIGAR_ZERO(s) \ 150 memset(s, '\0', sizeof(*(s))) 151#endif 152 153#ifdef WIN32 154#include <windows.h> 155sigar_uint64_t sigar_FileTimeToTime(FILETIME *ft); 156#else 157#include <string.h> 158#endif 159 160static const char* types[] = { 161 "none", 162 "regular", 163 "directory", 164 "character device", 165 "block device", 166 "pipe", 167 "symbolic link", 168 "socket", 169 "unknown" 170}; 171 172SIGAR_DECLARE(const char *) 173sigar_file_attrs_type_string_get(sigar_file_type_e type) 174{ 175 if ((type < SIGAR_FILETYPE_NOFILE) || 176 (type > SIGAR_FILETYPE_UNKFILE)) 177 { 178 type = SIGAR_FILETYPE_UNKFILE; 179 } 180 181 return types[type]; 182} 183 184static const sigar_uint64_t perm_modes[] = { 185 SIGAR_UREAD, SIGAR_UWRITE, SIGAR_UEXECUTE, 186 SIGAR_GREAD, SIGAR_GWRITE, SIGAR_GEXECUTE, 187 SIGAR_WREAD, SIGAR_WWRITE, SIGAR_WEXECUTE 188}; 189 190static const char perm_chars[] = "rwx"; 191 192SIGAR_DECLARE(char *) 193sigar_file_attrs_permissions_string_get(sigar_uint64_t permissions, 194 char *str) 195{ 196 char *ptr = str; 197 int i=0, j=0; 198 199 for (i=0; i<9; i+=3) { 200 for (j=0; j<3; j++) { 201 if (permissions & perm_modes[i+j]) { 202 *ptr = perm_chars[j]; 203 } 204 else { 205 *ptr = '-'; 206 } 207 ptr++; 208 } 209 } 210 211 *ptr = '\0'; 212 return str; 213} 214 215static const int perm_int[] = { 216 400, 200, 100, 217 40, 20, 10, 218 4, 2, 1 219}; 220 221SIGAR_DECLARE(int)sigar_file_attrs_mode_get(sigar_uint64_t permissions) 222{ 223 int i=0; 224 int perms = 0; 225 226 /* no doubt there is some fancy bitshifting 227 * to convert, but this works fine. 228 */ 229 for (i=0; i<9; i++) { 230 if (permissions & perm_modes[i]) { 231 perms += perm_int[i]; 232 } 233 } 234 235 return perms; 236} 237 238#define IS_DOTDIR(dir) \ 239 ((dir[0] == '.') && (!dir[1] || ((dir[1] == '.') && !dir[2]))) 240 241#define DIR_STAT_WARN() \ 242 sigar_log_printf(sigar, SIGAR_LOG_WARN, \ 243 "dir_stat: cannot stat `%s': %s", \ 244 name, \ 245 sigar_strerror(sigar, status)) 246 247#if defined(NETWARE) 248 249int sigar_dir_stat_get(sigar_t *sigar, 250 const char *dir, 251 sigar_dir_stat_t *dirstats) 252{ 253 return SIGAR_ENOTIMPL; 254} 255 256int sigar_file_attrs_get(sigar_t *sigar, 257 const char *file, 258 sigar_file_attrs_t *fileattrs) 259{ 260 return SIGAR_ENOTIMPL; 261} 262 263int sigar_link_attrs_get(sigar_t *sigar, 264 const char *file, 265 sigar_file_attrs_t *fileattrs) 266{ 267 return SIGAR_ENOTIMPL; 268} 269 270#elif defined(WIN32) 271 272#include <accctrl.h> 273#include <aclapi.h> 274 275static void fillin_fileattrs(sigar_file_attrs_t *finfo, 276 WIN32_FILE_ATTRIBUTE_DATA *wininfo, 277 int linkinfo) 278{ 279 DWORD *sizes = &wininfo->nFileSizeHigh; 280 281 finfo->atime = sigar_FileTimeToTime(&wininfo->ftLastAccessTime) / 1000; 282 finfo->ctime = sigar_FileTimeToTime(&wininfo->ftCreationTime) / 1000; 283 finfo->mtime = sigar_FileTimeToTime(&wininfo->ftLastWriteTime) / 1000; 284 285 finfo->size = 286 (sigar_uint64_t)sizes[1] | ((sigar_uint64_t)sizes[0] << 32); 287 288 if (linkinfo && 289 (wininfo->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { 290 finfo->type = SIGAR_FILETYPE_LNK; 291 } 292 else if (wininfo->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 293 finfo->type = SIGAR_FILETYPE_DIR; 294 } 295 else { 296 finfo->type = SIGAR_FILETYPE_REG; 297 } 298} 299 300static sigar_uint64_t convert_perms(ACCESS_MASK acc, sigar_uint64_t scope) 301{ 302 sigar_uint64_t perms = 0; 303 if (acc & FILE_EXECUTE) { 304 perms |= SIGAR_WEXECUTE; 305 } 306 if (acc & FILE_WRITE_DATA) { 307 perms |= SIGAR_WWRITE; 308 } 309 if (acc & FILE_READ_DATA) { 310 perms |= SIGAR_WREAD; 311 } 312 313 return (perms << scope); 314} 315 316static int get_security_info(sigar_t *sigar, 317 const char *file, 318 sigar_file_attrs_t *fileattrs) 319{ 320 DWORD retval; 321 PSID user = NULL, group = NULL, world = NULL; 322 PACL dacl = NULL; 323 PSECURITY_DESCRIPTOR pdesc = NULL; 324 SECURITY_INFORMATION sinfo = 325 OWNER_SECURITY_INFORMATION | 326 GROUP_SECURITY_INFORMATION | 327 DACL_SECURITY_INFORMATION; 328 TRUSTEE ident = {NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID}; 329 ACCESS_MASK acc; 330 SID_IDENTIFIER_AUTHORITY auth = SECURITY_WORLD_SID_AUTHORITY; 331 332 retval = GetNamedSecurityInfo((char *)file, 333 SE_FILE_OBJECT, 334 sinfo, 335 &user, 336 &group, 337 &dacl, 338 NULL, 339 &pdesc); 340 341 if (retval != ERROR_SUCCESS) { 342 return retval; 343 } 344 345 if (!AllocateAndInitializeSid(&auth, 1, SECURITY_WORLD_RID, 346 0, 0, 0, 0, 0, 0, 0, &world)) 347 { 348 world = NULL; 349 } 350 351 ident.TrusteeType = TRUSTEE_IS_USER; 352 ident.ptstrName = user; 353 if (GetEffectiveRightsFromAcl(dacl, &ident, &acc) == ERROR_SUCCESS) { 354 fileattrs->permissions |= convert_perms(acc, 8); 355 } 356 357 ident.TrusteeType = TRUSTEE_IS_GROUP; 358 ident.ptstrName = group; 359 if (GetEffectiveRightsFromAcl(dacl, &ident, &acc) == ERROR_SUCCESS) { 360 fileattrs->permissions |= convert_perms(acc, 4); 361 } 362 363 if (world) { 364 ident.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; 365 ident.ptstrName = world; 366 if (GetEffectiveRightsFromAcl(dacl, &ident, &acc) == ERROR_SUCCESS) { 367 fileattrs->permissions |= convert_perms(acc, 0); 368 } 369 } 370 371 if (world) { 372 FreeSid(world); 373 } 374 375 LocalFree(pdesc); 376 377 return SIGAR_OK; 378} 379 380static int fileattrs_get(sigar_t *sigar, 381 const char *file, 382 sigar_file_attrs_t *fileattrs, 383 int linkinfo) 384{ 385 BY_HANDLE_FILE_INFORMATION info; 386 WIN32_FILE_ATTRIBUTE_DATA attrs; 387 HANDLE handle; 388 DWORD flags; 389 390 SIGAR_ZERO(fileattrs); 391 392 if (!GetFileAttributesExA(file, 393 GetFileExInfoStandard, 394 &attrs)) 395 { 396 return GetLastError(); 397 } 398 399 fillin_fileattrs(fileattrs, &attrs, linkinfo); 400 401 flags = fileattrs->type == SIGAR_FILETYPE_DIR ? 402 FILE_FLAG_BACKUP_SEMANTICS : 403 FILE_ATTRIBUTE_NORMAL; 404 405 /** 406 * We need to set dwDesiredAccess to 0 to work in cases where GENERIC_READ can fail. 407 * 408 * see: http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx 409 */ 410 handle = CreateFile(file, 411 0, 412 0, 413 NULL, 414 OPEN_EXISTING, 415 flags, 416 NULL); 417 418 if (handle != INVALID_HANDLE_VALUE) { 419 if (GetFileInformationByHandle(handle, &info)) { 420 fileattrs->inode = 421 (long long)info.nFileIndexLow | 422 ((long long)info.nFileIndexHigh << 32); 423 fileattrs->device = info.dwVolumeSerialNumber; 424 fileattrs->nlink = info.nNumberOfLinks; 425 } 426 CloseHandle(handle); 427 } 428 429 get_security_info(sigar, file, fileattrs); 430 431 return SIGAR_OK; 432} 433 434SIGAR_DECLARE(int) sigar_file_attrs_get(sigar_t *sigar, 435 const char *file, 436 sigar_file_attrs_t *fileattrs) 437{ 438 return fileattrs_get(sigar, file, fileattrs, 0); 439} 440 441SIGAR_DECLARE(int) sigar_link_attrs_get(sigar_t *sigar, 442 const char *file, 443 sigar_file_attrs_t *fileattrs) 444{ 445 return fileattrs_get(sigar, file, fileattrs, 1); 446} 447 448static __inline int file_type(char *file) 449{ 450 WIN32_FILE_ATTRIBUTE_DATA attrs; 451 452 if (!GetFileAttributesExA(file, 453 GetFileExInfoStandard, 454 &attrs)) 455 { 456 return -1; 457 } 458 459 if (attrs.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { 460 return SIGAR_FILETYPE_LNK; 461 } 462 else if (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 463 return SIGAR_FILETYPE_DIR; 464 } 465 else { 466 return SIGAR_FILETYPE_REG; 467 } 468} 469 470static int dir_stat_get(sigar_t *sigar, 471 const char *dir, 472 sigar_dir_stat_t *dirstats, 473 int recurse) 474{ 475 int status; 476 char name[SIGAR_PATH_MAX+1]; 477 int len = strlen(dir); 478 int max = sizeof(name)-len-1; 479 char *ptr = name; 480 WIN32_FIND_DATA data; 481 HANDLE handle; 482 DWORD error; 483 char delim; 484 485 if (file_type((char *)dir) != SIGAR_FILETYPE_DIR) { 486 return ERROR_NO_MORE_FILES; 487 } 488 489 strncpy(name, dir, sizeof(name)); 490 ptr += len; 491 if (strchr(dir, '/')) { 492 delim = '/'; 493 } 494 else { 495 delim = '\\'; 496 } 497 if (name[len] != delim) { 498 *ptr++ = delim; 499 len++; 500 max--; 501 } 502 503 /* e.g. "C:\sigar\*" */ 504 name[len] = '*'; 505 name[len+1] = '\0'; 506 507 handle = FindFirstFile(name, &data); 508 if (handle == INVALID_HANDLE_VALUE) { 509 return GetLastError(); 510 } 511 512 do { 513 /* skip '.' and '..' */ 514 if (IS_DOTDIR(data.cFileName)) { 515 continue; 516 } 517 518 dirstats->disk_usage += 519 (data.nFileSizeHigh * (MAXDWORD+1)) + 520 data.nFileSizeLow; 521 522 /* e.g. "C:\sigar\lib" */ 523 strncpy(ptr, data.cFileName, max); 524 ptr[max] = '\0'; 525 526 switch (file_type(name)) { 527 case -1: 528 break; 529 case SIGAR_FILETYPE_REG: 530 ++dirstats->files; 531 break; 532 case SIGAR_FILETYPE_DIR: 533 ++dirstats->subdirs; 534 if (recurse) { 535 status = 536 dir_stat_get(sigar, name, 537 dirstats, recurse); 538 if (status != SIGAR_OK) { 539 DIR_STAT_WARN(); 540 } 541 } 542 break; 543 case SIGAR_FILETYPE_LNK: 544 ++dirstats->symlinks; 545 break; 546 case SIGAR_FILETYPE_CHR: 547 ++dirstats->chrdevs; 548 break; 549 case SIGAR_FILETYPE_BLK: 550 ++dirstats->blkdevs; 551 break; 552 case SIGAR_FILETYPE_SOCK: 553 ++dirstats->sockets; 554 break; 555 default: 556 ++dirstats->total; 557 } 558 } while (FindNextFile(handle, &data)); 559 560 error = GetLastError(); 561 562 FindClose(handle); 563 564 if (error != ERROR_NO_MORE_FILES) { 565 return error; 566 } 567 568 dirstats->total = 569 dirstats->files + 570 dirstats->subdirs + 571 dirstats->symlinks + 572 dirstats->chrdevs + 573 dirstats->blkdevs + 574 dirstats->sockets; 575 576 return SIGAR_OK; 577} 578 579#else 580 581#include <dirent.h> 582#include <errno.h> 583#include <sys/stat.h> 584#include <sys/types.h> 585 586static sigar_file_type_e filetype_from_mode(mode_t mode) 587{ 588 sigar_file_type_e type; 589 590 switch (mode & S_IFMT) { 591 case S_IFREG: 592 type = SIGAR_FILETYPE_REG; break; 593 case S_IFDIR: 594 type = SIGAR_FILETYPE_DIR; break; 595 case S_IFLNK: 596 type = SIGAR_FILETYPE_LNK; break; 597 case S_IFCHR: 598 type = SIGAR_FILETYPE_CHR; break; 599 case S_IFBLK: 600 type = SIGAR_FILETYPE_BLK; break; 601#if defined(S_IFFIFO) 602 case S_IFFIFO: 603 type = SIGAR_FILETYPE_PIPE; break; 604#endif 605#if !defined(BEOS) && defined(S_IFSOCK) 606 case S_IFSOCK: 607 type = SIGAR_FILETYPE_SOCK; break; 608#endif 609 610 default: 611 /* Work around missing S_IFxxx values above 612 * for Linux et al. 613 */ 614#if !defined(S_IFFIFO) && defined(S_ISFIFO) 615 if (S_ISFIFO(mode)) { 616 type = SIGAR_FILETYPE_PIPE; 617 } else 618#endif 619#if !defined(BEOS) && !defined(S_IFSOCK) && defined(S_ISSOCK) 620 if (S_ISSOCK(mode)) { 621 type = SIGAR_FILETYPE_SOCK; 622 } else 623#endif 624 type = SIGAR_FILETYPE_UNKFILE; 625 } 626 return type; 627} 628 629static sigar_uint64_t sigar_unix_mode2perms(mode_t mode) 630{ 631 sigar_uint64_t perms = 0; 632 633 if (mode & S_IRUSR) 634 perms |= SIGAR_UREAD; 635 if (mode & S_IWUSR) 636 perms |= SIGAR_UWRITE; 637 if (mode & S_IXUSR) 638 perms |= SIGAR_UEXECUTE; 639 640 if (mode & S_IRGRP) 641 perms |= SIGAR_GREAD; 642 if (mode & S_IWGRP) 643 perms |= SIGAR_GWRITE; 644 if (mode & S_IXGRP) 645 perms |= SIGAR_GEXECUTE; 646 647 if (mode & S_IROTH) 648 perms |= SIGAR_WREAD; 649 if (mode & S_IWOTH) 650 perms |= SIGAR_WWRITE; 651 if (mode & S_IXOTH) 652 perms |= SIGAR_WEXECUTE; 653 654 return perms; 655} 656 657static void copy_stat_info(sigar_file_attrs_t *fileattrs, 658 struct stat *info) 659{ 660 fileattrs->permissions = sigar_unix_mode2perms(info->st_mode); 661 fileattrs->type = filetype_from_mode(info->st_mode); 662 fileattrs->uid = info->st_uid; 663 fileattrs->gid = info->st_gid; 664 fileattrs->size = info->st_size; 665 fileattrs->inode = info->st_ino; 666 fileattrs->device = info->st_dev; 667 fileattrs->nlink = info->st_nlink; 668 fileattrs->atime = info->st_atime; 669 fileattrs->mtime = info->st_mtime; 670 fileattrs->ctime = info->st_ctime; 671 fileattrs->atime *= 1000; 672 fileattrs->mtime *= 1000; 673 fileattrs->ctime *= 1000; 674} 675 676int sigar_file_attrs_get(sigar_t *sigar, 677 const char *file, 678 sigar_file_attrs_t *fileattrs) 679{ 680 struct stat info; 681 682 if (stat(file, &info) == 0) { 683 copy_stat_info(fileattrs, &info); 684 return SIGAR_OK; 685 } 686 else { 687 return errno; 688 } 689} 690 691int sigar_link_attrs_get(sigar_t *sigar, 692 const char *file, 693 sigar_file_attrs_t *fileattrs) 694{ 695 struct stat info; 696 697 if (lstat(file, &info) == 0) { 698 copy_stat_info(fileattrs, &info); 699 return SIGAR_OK; 700 } 701 else { 702 return errno; 703 } 704} 705 706static int dir_stat_get(sigar_t *sigar, 707 const char *dir, 708 sigar_dir_stat_t *dirstats, 709 int recurse) 710{ 711 int status; 712 char name[SIGAR_PATH_MAX+1]; 713 int len = strlen(dir); 714 int max = sizeof(name)-len-1; 715 char *ptr = name; 716 DIR *dirp = opendir(dir); 717 struct dirent *ent; 718 struct stat info; 719#ifdef HAVE_READDIR_R 720 struct dirent dbuf; 721#endif 722 723 if (!dirp) { 724 return errno; 725 } 726 727 strncpy(name, dir, sizeof(name)); 728 ptr += len; 729 if (name[len] != '/') { 730 *ptr++ = '/'; 731 len++; 732 max--; 733 } 734 735#ifdef HAVE_READDIR_R 736 while (readdir_r(dirp, &dbuf, &ent) == 0) { 737 if (ent == NULL) { 738 break; 739 } 740#else 741 while ((ent = readdir(dirp))) { 742#endif 743 /* skip '.' and '..' */ 744 if (IS_DOTDIR(ent->d_name)) { 745 continue; 746 } 747 748 strncpy(ptr, ent->d_name, max); 749 ptr[max] = '\0'; 750 751 if (lstat(name, &info) != 0) { 752 continue; 753 } 754 755 dirstats->disk_usage += info.st_size; 756 757 switch (filetype_from_mode(info.st_mode)) { 758 case SIGAR_FILETYPE_REG: 759 ++dirstats->files; 760 break; 761 case SIGAR_FILETYPE_DIR: 762 ++dirstats->subdirs; 763 if (recurse) { 764 status = 765 dir_stat_get(sigar, name, 766 dirstats, recurse); 767 if (status != SIGAR_OK) { 768 DIR_STAT_WARN(); 769 } 770 } 771 break; 772 case SIGAR_FILETYPE_LNK: 773 ++dirstats->symlinks; 774 break; 775 case SIGAR_FILETYPE_CHR: 776 ++dirstats->chrdevs; 777 break; 778 case SIGAR_FILETYPE_BLK: 779 ++dirstats->blkdevs; 780 break; 781 case SIGAR_FILETYPE_SOCK: 782 ++dirstats->sockets; 783 break; 784 default: 785 ++dirstats->total; 786 } 787 } 788 789 dirstats->total = 790 dirstats->files + 791 dirstats->subdirs + 792 dirstats->symlinks + 793 dirstats->chrdevs + 794 dirstats->blkdevs + 795 dirstats->sockets; 796 797 closedir(dirp); 798 799 return SIGAR_OK; 800} 801 802#endif 803 804SIGAR_DECLARE(int) sigar_dir_stat_get(sigar_t *sigar, 805 const char *dir, 806 sigar_dir_stat_t *dirstats) 807{ 808 SIGAR_ZERO(dirstats); 809 return dir_stat_get(sigar, dir, dirstats, 0); 810} 811 812SIGAR_DECLARE(int) sigar_dir_usage_get(sigar_t *sigar, 813 const char *dir, 814 sigar_dir_usage_t *dirusage) 815{ 816 SIGAR_ZERO(dirusage); 817 return dir_stat_get(sigar, dir, dirusage, 1); 818} 819