diff options
-rw-r--r-- | DiskUsage.cpp | 145 | ||||
-rw-r--r-- | MobileCydia.mm | 40 | ||||
-rw-r--r-- | makefile | 8 | ||||
-rwxr-xr-x | sysroot.sh | 1 |
4 files changed, 157 insertions, 37 deletions
diff --git a/DiskUsage.cpp b/DiskUsage.cpp new file mode 100644 index 0000000..eece02c --- /dev/null +++ b/DiskUsage.cpp @@ -0,0 +1,145 @@ +/* Cydia - iPhone UIKit Front-End for Debian APT + * Copyright (C) 2008-2014 Jay Freeman (saurik) +*/ + +/* GNU General Public License, Version 3 {{{ */ +/* + * Cydia is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Cydia is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cydia. If not, see <http://www.gnu.org/licenses/>. +**/ +/* }}} */ + +#include <fcntl.h> +#include <dirent.h> +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <sys/stat.h> + +#define _syscall(expr) ({ decltype(expr) _value; for (;;) { \ + _value = (expr); \ + if ((long) _value != -1) \ + break; \ + if (errno != EINTR) { \ + perror(#expr); \ + return -1; \ + } \ +} _value; }) + +extern "C" int __getdirentries64(int, char *, int, long *); + +enum Recurse { + RecurseYes, + RecurseNo, + RecurseMaybe, +}; + +struct File { + int fd_; + + File(int fd); + ~File(); + + operator int() const; +}; + +File::File(int fd) : + fd_(fd) +{ +} + +File::~File() { + close(fd_); +} + +File::operator int() const { + return fd_; +} + +static bool DiskUsage(size_t &total, const char *path, size_t before, Recurse recurse) { + File fd(_syscall(open_dprotected_np(path, O_RDONLY | O_SYMLINK, 0, O_DP_GETRAWENCRYPTED))); + + struct stat stat; + _syscall(fstat(fd, &stat)); + total += stat.st_blocks * 512; + + if (recurse == RecurseMaybe) + switch (stat.st_mode & S_IFMT) { + case S_IFLNK: + return true; + default: + return false; + + case S_IFDIR: + recurse = RecurseYes; + break; + case S_IFREG: + recurse = RecurseNo; + break; + } + + if (recurse == RecurseNo) { + } else for (long address(0);;) { + char buffer[4096]; + int size(_syscall(__getdirentries64(fd, buffer, sizeof(buffer), &address))); + if (size == 0) + break; + + const char *next(buffer), *stop(next + size); + while (next != stop) { + const dirent *dir(reinterpret_cast<const dirent *>(next)); + const char *name(dir->d_name); + size_t after(strlen(name)); + + if (dir->d_ino == 0); + else if (after == 1 && name[0] == '.'); + else if (after == 2 && name[0] == '.' && name[1] == '.'); + else { + size_t both(before + 1 + after); + char sub[both + 1]; + memcpy(sub, path, before); + sub[before] = '/'; + memcpy(sub + before + 1, name, after); + sub[both] = '\0'; + + switch (dir->d_type) { + case DT_DIR: + if (!DiskUsage(total, sub, both, RecurseYes)) + return false; + break; + + case DT_LNK: + case DT_REG: + if (!DiskUsage(total, sub, both, RecurseNo)) + return false; + break; + + default: + return false; + } + } + + next += dir->d_reclen; + } + } + + return true; +} + +ssize_t DiskUsage(const char *path) { + size_t total(0); + if (!DiskUsage(total, path, strlen(path), RecurseMaybe)) + return -1; + return total; +} diff --git a/MobileCydia.mm b/MobileCydia.mm index 1968599..ca91d08 100644 --- a/MobileCydia.mm +++ b/MobileCydia.mm @@ -4728,41 +4728,13 @@ static _H<NSMutableSet> Diversions_; nil]; } -- (NSNumber *) du:(NSString *)path { - NSNumber *value(nil); - - int fds[2]; - _assert(pipe(fds) != -1); - - pid_t pid(ExecFork()); - if (pid == 0) { - _assert(dup2(fds[1], 1) != -1); - _assert(close(fds[0]) != -1); - _assert(close(fds[1]) != -1); - /* XXX: this should probably not use du */ - _root(execl("/usr/libexec/cydia/du", "du", "-s", [path UTF8String], NULL)); - exit(1); - } else { - _assert(close(fds[1]) != -1); +ssize_t DiskUsage(const char *path); - if (FILE *du = fdopen(fds[0], "r")) { - char line[1024]; - while (fgets(line, sizeof(line), du) != NULL) { - size_t length(strlen(line)); - while (length != 0 && line[length - 1] == '\n') - line[--length] = '\0'; - if (char *tab = strchr(line, '\t')) { - *tab = '\0'; - value = [NSNumber numberWithUnsignedLong:strtoul(line, NULL, 0)]; - } - } - - fclose(du); - } else - _assert(close(fds[0]) != -1); - } ReapZombie(pid); - - return value; +- (NSNumber *) du:(NSString *)path { + ssize_t usage(DiskUsage([path UTF8String])); + if (usage != -1) + usage /= 1024; + return [NSNumber numberWithUnsignedLong:usage]; } - (void) close { @@ -61,7 +61,7 @@ dirs := Menes CyteKit Cydia SDURLCache code := $(foreach dir,$(dirs),$(wildcard $(foreach ext,h hpp c cpp m mm,$(dir)/*.$(ext)))) code := $(filter-out SDURLCache/SDURLCacheTests.m,$(code)) -code += MobileCydia.mm Version.mm iPhonePrivate.h Cytore.hpp lookup3.c Sources.h Sources.mm +code += MobileCydia.mm Version.mm iPhonePrivate.h Cytore.hpp lookup3.c Sources.h Sources.mm DiskUsage.cpp source := $(filter %.m,$(code)) $(filter %.mm,$(code)) source += $(filter %.c,$(code)) $(filter %.cpp,$(code)) @@ -95,6 +95,11 @@ Objects/%.o: %.m $(header) @echo "[cycc] $<" @$(cycc) -c $< $(flags) +Objects/%.o: %.cpp $(header) + @mkdir -p $(dir $@) + @echo "[cycc] $<" + @$(cycc) -std=c++11 -c $< $(flags) $(xflags) + Objects/%.o: %.mm $(header) @mkdir -p $(dir $@) @echo "[cycc] $<" @@ -146,7 +151,6 @@ debs/cydia_$(version)_iphoneos-arm.deb: MobileCydia preinst postinst cfversion s mkdir -p _/usr/libexec cp -a Library _/usr/libexec/cydia - cp -a sysroot/usr/bin/du _/usr/libexec/cydia cp -a cfversion _/usr/libexec/cydia cp -a setnsfpn _/usr/libexec/cydia @@ -64,7 +64,6 @@ declare -A urls urls[apt7]=http://apt.saurik.com/debs/apt7_0.7.25.3-7_iphoneos-arm.deb urls[apt7-lib]=http://apt.saurik.com/debs/apt7-lib_0.7.25.3-12_iphoneos-arm.deb -urls[coreutils]=http://apt.saurik.com/debs/coreutils_7.4-11_iphoneos-arm.deb if [[ 0 ]]; then wget -qO- "${repository}dists/${distribution}/${component}/binary-${architecture}/Packages.bz2" | bzcat | { |