123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- #include "CFBundle.h"
- #ifdef __APPLE__
- #include "llvm/Support/FileSystem.h"
- #include "llvm/Support/Path.h"
- #include "llvm/Support/raw_ostream.h"
- #include <CoreFoundation/CoreFoundation.h>
- #include <assert.h>
- #include <glob.h>
- #include <memory>
- #endif
- namespace llvm {
- namespace dsymutil {
- #ifdef __APPLE__
- template <typename T> struct CFDeleter {
- void operator()(T *P) {
- if (P)
- ::CFRelease(P);
- }
- };
- template <typename T>
- using CFReleaser = std::unique_ptr<std::remove_pointer_t<T>,
- CFDeleter<std::remove_pointer_t<T>>>;
- class CFString : public CFReleaser<CFStringRef> {
- public:
- CFString(CFStringRef CFStr = nullptr) : CFReleaser<CFStringRef>(CFStr) {}
- const char *UTF8(std::string &Str) const {
- return CFString::UTF8(get(), Str);
- }
- CFIndex GetLength() const {
- if (CFStringRef Str = get())
- return CFStringGetLength(Str);
- return 0;
- }
- static const char *UTF8(CFStringRef CFStr, std::string &Str);
- };
- const char *CFString::UTF8(CFStringRef CFStr, std::string &Str) {
- if (!CFStr)
- return nullptr;
- const CFStringEncoding Encoding = kCFStringEncodingUTF8;
- CFIndex MaxUTF8StrLength = CFStringGetLength(CFStr);
- MaxUTF8StrLength =
- CFStringGetMaximumSizeForEncoding(MaxUTF8StrLength, Encoding);
- if (MaxUTF8StrLength > 0) {
- Str.resize(MaxUTF8StrLength);
- if (!Str.empty() &&
- CFStringGetCString(CFStr, &Str[0], Str.size(), Encoding)) {
- Str.resize(strlen(Str.c_str()));
- return Str.c_str();
- }
- }
- return nullptr;
- }
- class CFBundle : public CFReleaser<CFBundleRef> {
- public:
- CFBundle(StringRef Path) : CFReleaser<CFBundleRef>() { SetFromPath(Path); }
- CFBundle(CFURLRef Url)
- : CFReleaser<CFBundleRef>(Url ? ::CFBundleCreate(nullptr, Url)
- : nullptr) {}
-
- CFStringRef GetIdentifier() const {
- if (CFBundleRef bundle = get())
- return ::CFBundleGetIdentifier(bundle);
- return nullptr;
- }
-
- CFTypeRef GetValueForInfoDictionaryKey(CFStringRef key) const {
- if (CFBundleRef bundle = get())
- return ::CFBundleGetValueForInfoDictionaryKey(bundle, key);
- return nullptr;
- }
- private:
-
-
-
- void SetFromPath(StringRef Path);
- };
- void CFBundle::SetFromPath(StringRef Path) {
-
- reset();
- if (Path.empty() || !sys::fs::exists(Path))
- return;
- SmallString<256> RealPath;
- sys::fs::real_path(Path, RealPath, true);
- do {
-
- CFReleaser<CFURLRef> BundleURL(::CFURLCreateFromFileSystemRepresentation(
- kCFAllocatorDefault, (const UInt8 *)RealPath.data(), RealPath.size(),
- false));
- reset(::CFBundleCreate(kCFAllocatorDefault, BundleURL.get()));
-
- if (get() != nullptr) {
- if (GetIdentifier() != nullptr)
- return;
- reset();
- }
-
-
- sys::path::remove_filename(RealPath);
- } while (RealPath != sys::path::root_name(RealPath));
- }
- #endif
- CFBundleInfo getBundleInfo(StringRef ExePath) {
- CFBundleInfo BundleInfo;
- #ifdef __APPLE__
- auto PrintError = [&](CFTypeID TypeID) {
- CFString TypeIDCFStr(::CFCopyTypeIDDescription(TypeID));
- std::string TypeIDStr;
- errs() << "The Info.plist key \"CFBundleShortVersionString\" is"
- << "a " << TypeIDCFStr.UTF8(TypeIDStr)
- << ", but it should be a string in: " << ExePath << ".\n";
- };
- CFBundle Bundle(ExePath);
- if (CFStringRef BundleID = Bundle.GetIdentifier()) {
- CFString::UTF8(BundleID, BundleInfo.IDStr);
- if (CFTypeRef TypeRef =
- Bundle.GetValueForInfoDictionaryKey(CFSTR("CFBundleVersion"))) {
- CFTypeID TypeID = ::CFGetTypeID(TypeRef);
- if (TypeID == ::CFStringGetTypeID())
- CFString::UTF8((CFStringRef)TypeRef, BundleInfo.VersionStr);
- else
- PrintError(TypeID);
- }
- if (CFTypeRef TypeRef = Bundle.GetValueForInfoDictionaryKey(
- CFSTR("CFBundleShortVersionString"))) {
- CFTypeID TypeID = ::CFGetTypeID(TypeRef);
- if (TypeID == ::CFStringGetTypeID())
- CFString::UTF8((CFStringRef)TypeRef, BundleInfo.ShortVersionStr);
- else
- PrintError(TypeID);
- }
- }
- #endif
- return BundleInfo;
- }
- }
- }
|