X-Git-Url: https://git.saurik.com/ldid.git/blobdiff_plain/5c3034670da38ee2d42dec42b4c5a5df1815e843..886cb3f1cf485d307519e2024ef141314d42e713:/ldid.cpp diff --git a/ldid.cpp b/ldid.cpp index 68fdf7d..33b1859 100644 --- a/ldid.cpp +++ b/ldid.cpp @@ -48,7 +48,7 @@ #include #include -#include +#include #include "ldid.hpp" @@ -1387,8 +1387,13 @@ class Split { static void mkdir_p(const std::string &path) { if (path.empty()) return; +#ifdef __WIN32__ + if (_syscall(mkdir(path.c_str()), EEXIST) == -EEXIST) + return; +#else if (_syscall(mkdir(path.c_str(), 0755), EEXIST) == -EEXIST) return; +#endif auto slash(path.rfind('/', path.size() - 1)); if (slash == std::string::npos) return; @@ -1579,25 +1584,41 @@ void DiskFolder::Find(const std::string &root, const std::string &base, const Fu if (Starts(name, ".ldid.")) continue; + bool directory; + +#ifdef __WIN32__ + struct stat info; + _syscall(stat(path.c_str(), &info)); + if (false); + else if (S_ISDIR(info.st_mode)) + directory = true; + else if (S_ISREG(info.st_mode)) + directory = false; + else + _assert_(false, "st_mode=%x", info.st_mode); +#else switch (child->d_type) { case DT_DIR: - Find(root, base + name + "/", code); - break; - + directory = true; + break; case DT_REG: - code(base + name, fun([&](const Functor &code) { - std::string access(root + base + name); - _assert_(Open(access, fun([&](std::streambuf &data) { - NullBuffer save; - code(data, save); - })), "open(): %s", access.c_str()); - })); - break; - + directory = false; + break; default: _assert_(false, "d_type=%u", child->d_type); - break; } +#endif + + if (directory) + Find(root, base + name + "/", code); + else + code(base + name, fun([&](const Functor &code) { + std::string access(root + base + name); + _assert_(Open(access, fun([&](std::streambuf &data) { + NullBuffer save; + code(data, save); + })), "open(): %s", access.c_str()); + })); } } @@ -1622,22 +1643,57 @@ void DiskFolder::Find(const std::string &path, const Functor &code) { - return parent_->Save(path_ + path, code); + return parent_.Save(path_ + path, code); } bool SubFolder::Open(const std::string &path, const Functor &code) { - return parent_->Open(path_ + path, code); + return parent_.Open(path_ + path, code); } void SubFolder::Find(const std::string &path, const Functor &)> &)> &code) { - return parent_->Find(path_ + path, code); + return parent_.Find(path_ + path, code); +} + +UnionFolder::UnionFolder(Folder &parent) : + parent_(parent) +{ +} + +void UnionFolder::Save(const std::string &path, const Functor &code) { + return parent_.Save(path, code); +} + +bool UnionFolder::Open(const std::string &path, const Functor &code) { + auto file(files_.find(path)); + if (file == files_.end()) + return parent_.Open(path, code); + + auto &data(file->second); + data.pubseekpos(0, std::ios::in); + code(data); + return true; +} + +void UnionFolder::Find(const std::string &path, const Functor &)> &)> &code) { + parent_.Find(path, fun([&](const std::string &name, const Functor &)> &save) { + if (files_.find(name) == files_.end()) + code(name, save); + })); + + for (auto &file : files_) + code(file.first, fun([&](const Functor &code) { + parent_.Save(file.first, fun([&](std::streambuf &save) { + file.second.pubseekpos(0, std::ios::in); + code(file.second, save); + })); + })); } static size_t copy(std::streambuf &source, std::streambuf &target) { @@ -1653,27 +1709,32 @@ static size_t copy(std::streambuf &source, std::streambuf &target) { return total; } -static PList::Structure *plist(const std::string &data) { - if (!Starts(data, "bplist00")) - return PList::Structure::FromXml(data); - std::vector bytes(data.data(), data.data() + data.size()); - return PList::Structure::FromBin(bytes); +static plist_t plist(const std::string &data) { + plist_t plist(NULL); + if (Starts(data, "bplist00")) + plist_from_bin(data.data(), data.size(), &plist); + else + plist_from_xml(data.data(), data.size(), &plist); + _assert(plist != NULL); + return plist; } -static void plist_d(std::streambuf &buffer, const Functor &code) { +static void plist_d(std::streambuf &buffer, const Functor &code) { std::stringbuf data; copy(buffer, data); - PList::Structure *structure(plist(data.str())); - _scope({ delete structure; }); - auto dictionary(dynamic_cast(structure)); - _assert(dictionary != NULL); - code(dictionary); + auto node(plist(data.str())); + _scope({ plist_free(node); }); + _assert(plist_get_node_type(node) == PLIST_DICT); + code(node); } -static std::string plist_s(PList::Node *node) { - auto value(dynamic_cast(node)); - _assert(value != NULL); - return value->GetValue(); +static std::string plist_s(plist_t node) { + _assert(node != NULL); + _assert(plist_get_node_type(node) == PLIST_STRING); + char *data; + plist_get_string_val(node, &data); + _scope({ free(data); }); + return data; } enum Mode { @@ -1758,9 +1819,9 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k static const std::string info("Info.plist"); _assert_(folder.Open(info, fun([&](std::streambuf &buffer) { - plist_d(buffer, fun([&](PList::Dictionary *dictionary) { - executable = plist_s(((*dictionary)["CFBundleExecutable"])); - identifier = plist_s(((*dictionary)["CFBundleIdentifier"])); + plist_d(buffer, fun([&](plist_t node) { + executable = plist_s(plist_dict_get_item(node, "CFBundleExecutable")); + identifier = plist_s(plist_dict_get_item(node, "CFBundleIdentifier")); })); })), "open(): Info.plist"); @@ -1772,7 +1833,7 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k static const std::string signature("_CodeSignature/CodeResources"); folder.Open(signature, fun([&](std::streambuf &buffer) { - plist_d(buffer, fun([&](PList::Dictionary *dictionary) { + plist_d(buffer, fun([&](plist_t node) { // XXX: maybe attempt to preserve existing rules })); })); @@ -1811,7 +1872,7 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k if (!nested(name)) return; auto bundle(root + Split(name).dir); - SubFolder subfolder(&folder, bundle); + SubFolder subfolder(folder, bundle); Bundle(bundle, subfolder, key, local); })); @@ -1831,10 +1892,12 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k _assert(hash.size() == SHA_DIGEST_LENGTH); })); - PList::Dictionary plist; + auto plist(plist_new_dict()); + _scope({ plist_free(plist); }); for (const auto &version : versions) { - PList::Dictionary files; + auto files(plist_new_dict()); + plist_dict_set_item(plist, ("files" + version.first).c_str(), files); for (const auto &rule : version.second) rule.Compile(); @@ -1843,22 +1906,21 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k for (const auto &rule : version.second) if (rule(hash.first)) { if (rule.mode_ == NoMode) - files.Set(hash.first, PList::Data(hash.second)); + plist_dict_set_item(files, hash.first.c_str(), plist_new_data(hash.second.data(), hash.second.size())); else if (rule.mode_ == OptionalMode) { - PList::Dictionary entry; - entry.Set("hash", PList::Data(hash.second)); - entry.Set("optional", PList::Boolean(true)); - files.Set(hash.first, entry); + auto entry(plist_new_dict()); + plist_dict_set_item(entry, "hash", plist_new_data(hash.second.data(), hash.second.size())); + plist_dict_set_item(entry, "optional", plist_new_bool(true)); + plist_dict_set_item(files, hash.first.c_str(), entry); } break; } - - plist.Set("files" + version.first, files); } for (const auto &version : versions) { - PList::Dictionary rules; + auto rules(plist_new_dict()); + plist_dict_set_item(plist, ("rules" + version.first).c_str(), rules); std::multiset ordered; for (const auto &rule : version.second) @@ -1866,42 +1928,42 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k for (const auto &rule : ordered) if (rule->weight_ == 1 && rule->mode_ == NoMode) - rules.Set(rule->code_, PList::Boolean(true)); + plist_dict_set_item(rules, rule->code_.c_str(), plist_new_bool(true)); else { - PList::Dictionary entry; + auto entry(plist_new_dict()); + plist_dict_set_item(rules, rule->code_.c_str(), entry); switch (rule->mode_) { case NoMode: break; case OmitMode: - entry.Set("omit", PList::Boolean(true)); + plist_dict_set_item(entry, "omit", plist_new_bool(true)); break; case OptionalMode: - entry.Set("optional", PList::Boolean(true)); + plist_dict_set_item(entry, "optional", plist_new_bool(true)); break; case NestedMode: - entry.Set("nested", PList::Boolean(true)); + plist_dict_set_item(entry, "nested", plist_new_bool(true)); break; case TopMode: - entry.Set("top", PList::Boolean(true)); + plist_dict_set_item(entry, "top", plist_new_bool(true)); break; } if (rule->weight_ >= 10000) - entry.Set("weight", PList::Integer(rule->weight_)); + plist_dict_set_item(entry, "weight", plist_new_uint(rule->weight_)); else if (rule->weight_ != 1) - entry.Set("weight", PList::Real(rule->weight_)); - - rules.Set(rule->code_, entry); + plist_dict_set_item(entry, "weight", plist_new_real(rule->weight_)); } - - plist.Set("rules" + version.first, rules); } folder.Save(signature, fun([&](std::streambuf &save) { HashProxy proxy(local[signature], save); - auto xml(plist.ToXml()); - put(proxy, xml.data(), xml.size()); + char *xml(NULL); + uint32_t size; + plist_to_xml(plist, &xml, &size); + _scope({ free(xml); }); + put(proxy, xml, size); })); folder.Open(executable, fun([&](std::streambuf &buffer) {