[llvm] r321522 - [dsymutil][NFC] Replace calls to CoreFoundation with LLVM equivalent.

Jonas Devlieghere via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 28 06:05:50 PST 2017


Author: jdevlieghere
Date: Thu Dec 28 06:05:49 2017
New Revision: 321522

URL: http://llvm.org/viewvc/llvm-project?rev=321522&view=rev
Log:
[dsymutil][NFC] Replace calls to CoreFoundation with LLVM equivalent.

This patch replaces a block of logic that was implemented using
CoreFoundations calls with functionally equivalent logic that makes use
of LLVM libraries.

Modified:
    llvm/trunk/tools/dsymutil/CFBundle.cpp

Modified: llvm/trunk/tools/dsymutil/CFBundle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/CFBundle.cpp?rev=321522&r1=321521&r2=321522&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/CFBundle.cpp (original)
+++ llvm/trunk/tools/dsymutil/CFBundle.cpp Thu Dec 28 06:05:49 2017
@@ -11,6 +11,7 @@
 
 #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>
@@ -56,7 +57,7 @@ public:
   static const char *UTF8(CFStringRef CFStr, std::string &Str);
 };
 
-/// Static function that puts a copy of the UTF8 contents of CFStringRef into
+/// Static function that puts a copy of the UTF-8 contents of CFStringRef into
 /// std::string and returns the C string pointer that is contained in the
 /// std::string when successful, nullptr otherwise.
 ///
@@ -85,13 +86,10 @@ const char *CFString::UTF8(CFStringRef C
 /// RAII wrapper around CFBundleRef.
 class CFBundle : public CFReleaser<CFBundleRef> {
 public:
-  CFBundle(const char *Path = nullptr) : CFReleaser<CFBundleRef>() {
-    if (Path && Path[0])
-      SetFromPath(Path);
-  }
+  CFBundle(StringRef Path) : CFReleaser<CFBundleRef>() { SetFromPath(Path); }
 
-  CFBundle(CFURLRef url)
-      : CFReleaser<CFBundleRef>(url ? ::CFBundleCreate(nullptr, url)
+  CFBundle(CFURLRef Url)
+      : CFReleaser<CFBundleRef>(Url ? ::CFBundleCreate(nullptr, Url)
                                     : nullptr) {}
 
   /// Return the bundle identifier.
@@ -109,67 +107,49 @@ public:
   }
 
 private:
-  /// Update this instance with a new bundle created from the given path.
-  bool SetFromPath(const char *Path);
+  /// Helper to initialize this instance with a new bundle created from the
+  /// given path. This function will recursively remove components from the
+  /// path in its search for the nearest Info.plist.
+  void SetFromPath(StringRef Path);
 };
 
-bool CFBundle::SetFromPath(const char *InPath) {
-  // Release our old bundle and URL.
+void CFBundle::SetFromPath(StringRef Path) {
+  // Start from an empty/invalid CFBundle.
   reset();
 
-  if (InPath && InPath[0]) {
-    char ResolvedPath[PATH_MAX];
-    const char *Path = ::realpath(InPath, ResolvedPath);
-    if (Path == nullptr)
-      Path = InPath;
+  if (Path.empty() || !sys::fs::exists(Path))
+    return;
 
-    CFAllocatorRef Allocator = kCFAllocatorDefault;
-    // Make our Bundle URL.
-    CFReleaser<CFURLRef> BundleURL(::CFURLCreateFromFileSystemRepresentation(
-        Allocator, (const UInt8 *)Path, strlen(Path), false));
-    if (BundleURL.get()) {
-      CFIndex LastLength = LONG_MAX;
-
-      while (BundleURL.get() != nullptr) {
-        // Check the Path range and make sure we didn't make it to just "/",
-        // ".", or "..".
-        CFRange rangeIncludingSeparators;
-        CFRange range = ::CFURLGetByteRangeForComponent(
-            BundleURL.get(), kCFURLComponentPath, &rangeIncludingSeparators);
-        if (range.length > LastLength)
-          break;
-
-        reset(::CFBundleCreate(Allocator, BundleURL.get()));
-        if (get() != nullptr) {
-          if (GetIdentifier() != nullptr)
-            break;
-          reset();
-        }
-        BundleURL.reset(::CFURLCreateCopyDeletingLastPathComponent(
-            Allocator, BundleURL.get()));
+  SmallString<256> RealPath;
+  sys::fs::real_path(Path, RealPath, /*expand_tilde*/ true);
 
-        LastLength = range.length;
-      }
+  do {
+    // Create a CFURL from the current path and use it to create a CFBundle.
+    CFReleaser<CFURLRef> BundleURL(::CFURLCreateFromFileSystemRepresentation(
+        kCFAllocatorDefault, (const UInt8 *)RealPath.data(), RealPath.size(),
+        false));
+    reset(::CFBundleCreate(kCFAllocatorDefault, BundleURL.get()));
+
+    // If we have a valid bundle and find its identifier we are done.
+    if (get() != nullptr) {
+      if (GetIdentifier() != nullptr)
+        return;
+      reset();
     }
-  }
 
-  return get() != nullptr;
+    // Remove the last component of the path and try again until there's
+    // nothing left but the root.
+    sys::path::remove_filename(RealPath);
+  } while (RealPath != sys::path::root_name(RealPath));
 }
-
 #endif
 
-/// On Darwin, try and find the original executable's Info.plist information
-/// using CoreFoundation calls by creating a URL for the executable and
-/// chopping off the last Path component. The CFBundle can then get the
-/// identifier and grab any needed information from it directly. Return default
-/// CFBundleInfo on other platforms.
+/// On Darwin, try and find the original executable's Info.plist to extract
+/// information about the bundle. Return default values on other platforms.
 CFBundleInfo getBundleInfo(StringRef ExePath) {
   CFBundleInfo BundleInfo;
 
 #ifdef __APPLE__
-  if (ExePath.empty() || !sys::fs::exists(ExePath))
-    return BundleInfo;
-
   auto PrintError = [&](CFTypeID TypeID) {
     CFString TypeIDCFStr(::CFCopyTypeIDDescription(TypeID));
     std::string TypeIDStr;
@@ -178,7 +158,7 @@ CFBundleInfo getBundleInfo(StringRef Exe
            << ", but it should be a string in: " << ExePath << ".\n";
   };
 
-  CFBundle Bundle(ExePath.data());
+  CFBundle Bundle(ExePath);
   if (CFStringRef BundleID = Bundle.GetIdentifier()) {
     CFString::UTF8(BundleID, BundleInfo.IDStr);
     if (CFTypeRef TypeRef =




More information about the llvm-commits mailing list