From e1d26767107f358107ca0283836b111ddecb5d92 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Sun, 12 Mar 2017 16:58:35 -0700 Subject: Report progress (in terms of percent and logging). --- ldid.cpp | 122 +++++++++++++++++++++++++++++++++++++++------------------------ ldid.hpp | 14 ++++---- 2 files changed, 82 insertions(+), 54 deletions(-) diff --git a/ldid.cpp b/ldid.cpp index 2b755f4..751b99a 100644 --- a/ldid.cpp +++ b/ldid.cpp @@ -475,6 +475,8 @@ struct encryption_info_command { #define BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED 0xb0 #define BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0xc0 +static auto dummy([](double) {}); + static std::streamsize read(std::streambuf &stream, void *data, size_t size) { auto writ(stream.sgetn(static_cast(data), size)); _assert(writ >= 0); @@ -489,6 +491,16 @@ static inline void put(std::streambuf &stream, const void *data, size_t size) { _assert(stream.sputn(static_cast(data), size) == size); } +static inline void put(std::streambuf &stream, const void *data, size_t size, const ldid::Functor &percent) { + percent(0); + for (size_t total(0); total != size;) { + auto writ(std::min(size - total, size_t(4096 * 4))); + _assert(stream.sputn(static_cast(data) + total, writ) == writ); + total += writ; + percent(double(total) / size); + } +} + static size_t most(std::streambuf &stream, void *data, size_t size) { size_t total(size); while (size > 0) @@ -1010,7 +1022,7 @@ std::string Analyze(const void *data, size_t size) { return entitlements; } -static void Allocate(const void *idata, size_t isize, std::streambuf &output, const Functor &allocate, const Functor &save) { +static void Allocate(const void *idata, size_t isize, std::streambuf &output, const Functor &allocate, const Functor &)> &save, const Functor &percent) { FatHeader source(const_cast(idata), isize); size_t offset(0); @@ -1190,13 +1202,13 @@ static void Allocate(const void *idata, size_t isize, std::streambuf &output, co std::string overlap(altern.str()); overlap.append(top + overlap.size(), Align(overlap.size(), 0x1000) - overlap.size()); - put(output, top + (position - begin), allocation.size_ - (position - begin)); + put(output, top + (position - begin), allocation.size_ - (position - begin), percent); position = begin + allocation.size_; pad(output, allocation.limit_ - allocation.size_); position += allocation.limit_ - allocation.size_; - size_t saved(save(mach_header, output, allocation.limit_, overlap, top)); + size_t saved(save(mach_header, output, allocation.limit_, overlap, top, percent)); if (allocation.alloc_ > saved) pad(output, allocation.alloc_ - saved); else @@ -1511,7 +1523,7 @@ static void Commit(const std::string &path, const std::string &temp) { namespace ldid { -std::vector Sign(const void *idata, size_t isize, std::streambuf &output, const std::string &identifier, const std::string &entitlements, const std::string &requirement, const std::string &key, const Slots &slots) { +std::vector Sign(const void *idata, size_t isize, std::streambuf &output, const std::string &identifier, const std::string &entitlements, const std::string &requirement, const std::string &key, const Slots &slots, const Functor &percent) { std::vector hash(LDID_SHA1_DIGEST_LENGTH); std::string team; @@ -1581,7 +1593,7 @@ std::vector Sign(const void *idata, size_t isize, std::streambuf &output, uint32_t normal((size + PageSize_ - 1) / PageSize_); alloc = Align(alloc + (special + normal) * LDID_SHA1_DIGEST_LENGTH, 16); return alloc; - }), fun([&](const MachHeader &mach_header, std::streambuf &output, size_t limit, const std::string &overlap, const char *top) -> size_t { + }), fun([&](const MachHeader &mach_header, std::streambuf &output, size_t limit, const std::string &overlap, const char *top, const Functor &percent) -> size_t { Blobs blobs; if (true) { @@ -1672,11 +1684,15 @@ std::vector Sign(const void *idata, size_t isize, std::streambuf &output, memcpy(hashes - slot.first, slot.second.data(), slot.second.size()); } + percent(0); if (normal != 1) - for (size_t i = 0; i != normal - 1; ++i) + for (size_t i = 0; i != normal - 1; ++i) { sha1(hashes[i].sha1_, (PageSize_ * i < overlap.size() ? overlap.data() : top) + PageSize_ * i, PageSize_); + percent(double(i) / normal); + } if (normal != 0) sha1(hashes[normal - 1].sha1_, top + PageSize_ * (normal - 1), ((limit - 1) % PageSize_) + 1); + percent(1); put(data, storage.data(), sizeof(Digest) * storage.size()); @@ -1703,18 +1719,18 @@ std::vector Sign(const void *idata, size_t isize, std::streambuf &output, #endif return put(output, CSMAGIC_EMBEDDED_SIGNATURE, blobs); - })); + }), percent); return hash; } #ifndef LDID_NOTOOLS -static void Unsign(void *idata, size_t isize, std::streambuf &output) { +static void Unsign(void *idata, size_t isize, std::streambuf &output, const Functor &percent) { Allocate(idata, isize, output, fun([](const MachHeader &mach_header, size_t size) -> size_t { return 0; - }), fun([](const MachHeader &mach_header, std::streambuf &output, size_t limit, const std::string &overlap, const char *top) -> size_t { + }), fun([](const MachHeader &mach_header, std::streambuf &output, size_t limit, const std::string &overlap, const char *top, const Functor &percent) -> size_t { return 0; - })); + }), percent); } std::string DiskFolder::Path(const std::string &path) const { @@ -1814,11 +1830,14 @@ bool DiskFolder::Look(const std::string &path) const { return _syscall(access(Path(path).c_str(), R_OK), ENOENT) == 0; } -void DiskFolder::Open(const std::string &path, const Functor &code) const { +void DiskFolder::Open(const std::string &path, const Functor &code) const { std::filebuf data; auto result(data.open(Path(path).c_str(), std::ios::binary | std::ios::in)); _assert_(result == &data, "DiskFolder::Open(%s)", path.c_str()); - code(data, NULL); + + auto length(data.pubseekoff(0, std::ios::end, std::ios::in)); + data.pubseekpos(0, std::ios::in); + code(data, length, NULL); } void DiskFolder::Find(const std::string &path, const Functor &code, const Functor &)> &link) const { @@ -1840,7 +1859,7 @@ bool SubFolder::Look(const std::string &path) const { return parent_.Look(path_ + path); } -void SubFolder::Open(const std::string &path, const Functor &code) const { +void SubFolder::Open(const std::string &path, const Functor &code) const { return parent_.Open(path_ + path, code); } @@ -1855,7 +1874,7 @@ std::string UnionFolder::Map(const std::string &path) const { return remap->second; } -void UnionFolder::Map(const std::string &path, const Functor &code, const std::string &file, const Functor &)> &save) const { +void UnionFolder::Map(const std::string &path, const Functor &code, const std::string &file, const Functor &)> &save) const { if (file.size() >= path.size() && file.substr(0, path.size()) == path) code(file.substr(path.size())); } @@ -1876,29 +1895,31 @@ bool UnionFolder::Look(const std::string &path) const { return parent_.Look(Map(path)); } -void UnionFolder::Open(const std::string &path, const Functor &code) const { +void UnionFolder::Open(const std::string &path, const Functor &code) const { auto file(resets_.find(path)); if (file == resets_.end()) return parent_.Open(Map(path), code); auto &entry(file->second); auto &data(entry.first); + auto length(data.pubseekoff(0, std::ios::end, std::ios::in)); data.pubseekpos(0, std::ios::in); - code(data, entry.second); + code(data, length, entry.second); } void UnionFolder::Find(const std::string &path, const Functor &code, const Functor &)> &link) const { for (auto &reset : resets_) - Map(path, code, reset.first, fun([&](const Functor &code) { + Map(path, code, reset.first, fun([&](const Functor &code) { auto &entry(reset.second); + auto length(entry.first.pubseekoff(0, std::ios::end, std::ios::in)); entry.first.pubseekpos(0, std::ios::in); - code(entry.first, entry.second); + code(entry.first, length, entry.second); })); for (auto &remap : remaps_) - Map(path, code, remap.first, fun([&](const Functor &code) { - parent_.Open(remap.second, fun([&](std::streambuf &data, const void *flag) { - code(data, flag); + Map(path, code, remap.first, fun([&](const Functor &code) { + parent_.Open(remap.second, fun([&](std::streambuf &data, size_t length, const void *flag) { + code(data, length, flag); })); })); @@ -1912,17 +1933,18 @@ void UnionFolder::Find(const std::string &path, const Functor &percent) { + percent(0); size_t total(0); for (;;) { - char data[4096]; + char data[4096 * 4]; size_t writ(source.sgetn(data, sizeof(data))); if (writ == 0) break; _assert(target.sputn(data, writ) == writ); total += writ; + percent(double(total) / length); } - return total; } #ifndef LDID_NOPLIST @@ -1936,9 +1958,9 @@ static plist_t plist(const std::string &data) { return plist; } -static void plist_d(std::streambuf &buffer, const Functor &code) { +static void plist_d(std::streambuf &buffer, size_t length, const Functor &code) { std::stringbuf data; - copy(buffer, data); + copy(buffer, data, length, ldid::fun(dummy)); auto node(plist(data.str())); _scope({ plist_free(node); }); _assert(plist_get_node_type(node) == PLIST_DICT); @@ -2040,20 +2062,20 @@ struct RuleCode { }; #ifndef LDID_NOPLIST -static std::vector Sign(const uint8_t *prefix, size_t size, std::streambuf &buffer, Hash &hash, std::streambuf &save, const std::string &identifier, const std::string &entitlements, const std::string &requirement, const std::string &key, const Slots &slots) { +static std::vector Sign(const uint8_t *prefix, size_t size, std::streambuf &buffer, Hash &hash, std::streambuf &save, const std::string &identifier, const std::string &entitlements, const std::string &requirement, const std::string &key, const Slots &slots, size_t length, const Functor &percent) { // XXX: this is a miserable fail std::stringbuf temp; put(temp, prefix, size); - size += copy(buffer, temp); + copy(buffer, temp, length - size, percent); // XXX: this is a stupid hack - pad(temp, 0x10 - (size & 0xf)); + pad(temp, 0x10 - (length & 0xf)); auto data(temp.str()); HashProxy proxy(hash, save); - return Sign(data.data(), data.size(), proxy, identifier, entitlements, requirement, key, slots); + return Sign(data.data(), data.size(), proxy, identifier, entitlements, requirement, key, slots, percent); } -Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std::map &remote, const std::string &requirement, const Functor &alter) { +Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std::map &remote, const std::string &requirement, const Functor &alter, const Functor &progress, const Functor &percent) { std::string executable; std::string identifier; @@ -2065,8 +2087,8 @@ Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std info = "Resources/" + info; } - folder.Open(info, fun([&](std::streambuf &buffer, const void *flag) { - plist_d(buffer, fun([&](plist_t node) { + folder.Open(info, fun([&](std::streambuf &buffer, size_t length, const void *flag) { + plist_d(buffer, length, fun([&](plist_t node) { executable = plist_s(plist_dict_get_item(node, "CFBundleExecutable")); identifier = plist_s(plist_dict_get_item(node, "CFBundleIdentifier")); })); @@ -2078,12 +2100,12 @@ Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std } std::string entitlements; - folder.Open(executable, fun([&](std::streambuf &buffer, const void *flag) { + folder.Open(executable, fun([&](std::streambuf &buffer, size_t length, const void *flag) { // XXX: this is a miserable fail std::stringbuf temp; - auto size(copy(buffer, temp)); + copy(buffer, temp, length, percent); // XXX: this is a stupid hack - pad(temp, 0x10 - (size & 0xf)); + pad(temp, 0x10 - (length & 0xf)); auto data(temp.str()); entitlements = alter(root, Analyze(data.data(), data.size())); })); @@ -2138,7 +2160,8 @@ Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std SubFolder subfolder(folder, bundle); bundles[nested[1]] = Sign(bundle, subfolder, key, local, "", Starts(name, "PlugIns/") ? alter : - static_cast &>(fun([&](const std::string &, const std::string &entitlements) -> std::string { return entitlements; }))); + static_cast &>(fun([&](const std::string &, const std::string &entitlements) -> std::string { return entitlements; })) + , progress, percent); }), fun([&](const std::string &name, const Functor &read) { })); @@ -2168,7 +2191,9 @@ Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std return; auto &hash(local[name]); - folder.Open(name, fun([&](std::streambuf &data, const void *flag) { + folder.Open(name, fun([&](std::streambuf &data, size_t length, const void *flag) { + progress(root + name); + union { struct { uint32_t magic; @@ -2191,7 +2216,7 @@ Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std case MH_CIGAM: case MH_CIGAM_64: folder.Save(name, true, flag, fun([&](std::streambuf &save) { Slots slots; - Sign(header.bytes, size, data, hash, save, identifier, "", "", key, slots); + Sign(header.bytes, size, data, hash, save, identifier, "", "", key, slots, length, percent); })); return; } @@ -2199,7 +2224,7 @@ Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std folder.Save(name, false, flag, fun([&](std::streambuf &save) { HashProxy proxy(hash, save); put(proxy, header.bytes, size); - copy(data, proxy); + copy(data, proxy, length - size, percent); })); })); }), fun([&](const std::string &name, const Functor &read) { @@ -2314,12 +2339,13 @@ Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std Bundle bundle; bundle.path = executable; - folder.Open(executable, fun([&](std::streambuf &buffer, const void *flag) { + folder.Open(executable, fun([&](std::streambuf &buffer, size_t length, const void *flag) { + progress(root + executable); folder.Save(executable, true, flag, fun([&](std::streambuf &save) { Slots slots; slots[1] = local.at(info); slots[3] = local.at(signature); - bundle.hash = Sign(NULL, 0, buffer, local[executable], save, identifier, entitlements, requirement, key, slots); + bundle.hash = Sign(NULL, 0, buffer, local[executable], save, identifier, entitlements, requirement, key, slots, length, percent); })); })); @@ -2329,9 +2355,9 @@ Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std return bundle; } -Bundle Sign(const std::string &root, Folder &folder, const std::string &key, const std::string &requirement, const Functor &alter) { +Bundle Sign(const std::string &root, Folder &folder, const std::string &key, const std::string &requirement, const Functor &alter, const Functor &progress, const Functor &percent) { std::map local; - return Sign(root, folder, key, local, requirement, alter); + return Sign(root, folder, key, local, requirement, alter, progress, percent); } #endif @@ -2508,7 +2534,9 @@ int main(int argc, char *argv[]) { #ifndef LDID_NOPLIST _assert(!flag_r); ldid::DiskFolder folder(path); - path += "/" + Sign("", folder, key, requirement, ldid::fun([&](const std::string &, const std::string &) -> std::string { return entitlements; })).path; + path += "/" + Sign("", folder, key, requirement, ldid::fun([&](const std::string &, const std::string &) -> std::string { return entitlements; }) + , ldid::fun([&](const std::string &) {}), ldid::fun(dummy) + ).path; #else _assert(false); #endif @@ -2520,10 +2548,10 @@ int main(int argc, char *argv[]) { auto temp(Temporary(output, split)); if (flag_r) - ldid::Unsign(input.data(), input.size(), output); + ldid::Unsign(input.data(), input.size(), output, ldid::fun(dummy)); else { std::string identifier(flag_I ?: split.base.c_str()); - ldid::Sign(input.data(), input.size(), output, identifier, entitlements, requirement, key, slots); + ldid::Sign(input.data(), input.size(), output, identifier, entitlements, requirement, key, slots, ldid::fun(dummy)); } Commit(path, temp); diff --git a/ldid.hpp b/ldid.hpp index ce9d8d0..a628754 100644 --- a/ldid.hpp +++ b/ldid.hpp @@ -52,7 +52,7 @@ class Folder { public: virtual void Save(const std::string &path, bool edit, const void *flag, const Functor &code) = 0; virtual bool Look(const std::string &path) const = 0; - virtual void Open(const std::string &path, const Functor &code) const = 0; + virtual void Open(const std::string &path, const Functor &code) const = 0; virtual void Find(const std::string &path, const Functor &code, const Functor &)> &link) const = 0; }; @@ -75,7 +75,7 @@ class DiskFolder : virtual void Save(const std::string &path, bool edit, const void *flag, const Functor &code); virtual bool Look(const std::string &path) const; - virtual void Open(const std::string &path, const Functor &code) const; + virtual void Open(const std::string &path, const Functor &code) const; virtual void Find(const std::string &path, const Functor &code, const Functor &)> &link) const; }; @@ -91,7 +91,7 @@ class SubFolder : virtual void Save(const std::string &path, bool edit, const void *flag, const Functor &code); virtual bool Look(const std::string &path) const; - virtual void Open(const std::string &path, const Functor &code) const; + virtual void Open(const std::string &path, const Functor &code) const; virtual void Find(const std::string &path, const Functor &code, const Functor &)> &link) const; }; @@ -119,14 +119,14 @@ class UnionFolder : mutable std::map> resets_; std::string Map(const std::string &path) const; - void Map(const std::string &path, const Functor &code, const std::string &file, const Functor &)> &save) const; + void Map(const std::string &path, const Functor &code, const std::string &file, const Functor &)> &save) const; public: UnionFolder(Folder &parent); virtual void Save(const std::string &path, bool edit, const void *flag, const Functor &code); virtual bool Look(const std::string &path) const; - virtual void Open(const std::string &path, const Functor &code) const; + virtual void Open(const std::string &path, const Functor &code) const; virtual void Find(const std::string &path, const Functor &code, const Functor &)> &link) const; void operator ()(const std::string &from) { @@ -151,11 +151,11 @@ struct Bundle { std::vector hash; }; -Bundle Sign(const std::string &root, Folder &folder, const std::string &key, const std::string &requirement, const Functor &alter); +Bundle Sign(const std::string &root, Folder &folder, const std::string &key, const std::string &requirement, const Functor &alter, const Functor &progress, const Functor &percent); typedef std::map> Slots; -std::vector Sign(const void *idata, size_t isize, std::streambuf &output, const std::string &identifier, const std::string &entitlements, const std::string &requirement, const std::string &key, const Slots &slots); +std::vector Sign(const void *idata, size_t isize, std::streambuf &output, const std::string &identifier, const std::string &entitlements, const std::string &requirement, const std::string &key, const Slots &slots, const Functor &percent); } -- cgit v1.2.3-56-ge451