]>
git.saurik.com Git - cydia.git/blob - DiskUsage.cpp
   1 /* Cydia - iPhone UIKit Front-End for Debian APT 
   2  * Copyright (C) 2008-2015  Jay Freeman (saurik) 
   5 /* GNU General Public License, Version 3 {{{ */ 
   7  * Cydia is free software: you can redistribute it and/or modify 
   8  * it under the terms of the GNU General Public License as published 
   9  * by the Free Software Foundation, either version 3 of the License, 
  10  * or (at your option) any later version. 
  12  * Cydia is distributed in the hope that it will be useful, but 
  13  * WITHOUT ANY WARRANTY; without even the implied warranty of 
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  15  * GNU General Public License for more details. 
  17  * You should have received a copy of the GNU General Public License 
  18  * along with Cydia.  If not, see <http://www.gnu.org/licenses/>. 
  30 #define _syscall(expr) ({ decltype(expr) _value; for (;;) { \ 
  32     if ((long) _value != -1) \ 
  34     if (errno != EINTR) { \ 
  40 extern "C" int __getdirentries64(int, char *, int, long *); 
  66 File::operator int() const { 
  70 static bool DiskUsage(size_t &total
, const char *path
, size_t before
, Recurse recurse
) { 
  71     File 
fd(_syscall(open_dprotected_np(path
, O_RDONLY 
| O_SYMLINK
, 0, O_DP_GETRAWENCRYPTED
))); 
  74     _syscall(fstat(fd
, &stat
)); 
  75     total 
+= stat
.st_blocks 
* 512; 
  77     if (recurse 
== RecurseMaybe
) 
  78         switch (stat
.st_mode 
& S_IFMT
) { 
  92     if (recurse 
== RecurseNo
) { 
  93     } else for (long address(0);;) { 
  95         int size(_syscall(__getdirentries64(fd
, buffer
, sizeof(buffer
), &address
))); 
  99         const char *next(buffer
), *stop(next 
+ size
); 
 100         while (next 
!= stop
) { 
 101             const dirent 
*dir(reinterpret_cast<const dirent 
*>(next
)); 
 102             const char *name(dir
->d_name
); 
 103             size_t after(strlen(name
)); 
 105             if (dir
->d_ino 
== 0); 
 106             else if (after 
== 1 && name
[0] == '.'); 
 107             else if (after 
== 2 && name
[0] == '.' && name
[1] == '.'); 
 109                 size_t both(before 
+ 1 + after
); 
 111                 memcpy(sub
, path
, before
); 
 113                 memcpy(sub 
+ before 
+ 1, name
, after
); 
 116                 switch (dir
->d_type
) { 
 118                         if (!DiskUsage(total
, sub
, both
, RecurseYes
)) 
 124                         if (!DiskUsage(total
, sub
, both
, RecurseNo
)) 
 133             next 
+= dir
->d_reclen
; 
 140 ssize_t 
DiskUsage(const char *path
) { 
 142     if (!DiskUsage(total
, path
, strlen(path
), RecurseMaybe
))