]>
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
))