[PATCH] D19842: In openFileForRead, attempt to fetch the actual name of the file on disk -- including case -- so that clang can later warn about non-portable #include and #import directives.

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Tue May 3 12:51:56 PDT 2016


majnemer added a subscriber: majnemer.

================
Comment at: lib/Support/Unix/Path.inc:522
@@ +521,3 @@
+  // Attempt to get the real name of the file, if the user asked
+  if(RealPath) {
+    RealPath->clear();
----------------
I'd go for an early return to reduce indentation.

================
Comment at: lib/Support/Unix/Path.inc:524-547
@@ +523,26 @@
+    RealPath->clear();
+  #if 0 //__APPLE__
+    // On MacOS, fgetattrlist is the most reliable way to get a properly-cased
+    // path.
+    // BUGBUG commented out since fgetattrlist/ATTR_CMN_NAME seems to only
+    // fetch the file *name* and not the path.
+    struct attrlist attrList;
+    memset(&attrList, 0, sizeof(attrList));
+    attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
+    attrList.commonattr = ATTR_CMN_NAME;
+    struct NameAttr {
+      u_int32_t totalByteCount;
+      struct attrreference attrRef;
+      char Name[NAME_MAX * 3 + 1]; // Large enough for NAME_MAX UTF8 characters
+    };
+    union {
+      NameAttr nameAttr;
+      char Buffer[sizeof(nameAttr)];
+    };
+    if (fgetattrlist(ResultFD, &attrList, Buffer, sizeof(Buffer), 0) != -1) {
+      assert(nameAttr.attrRef.attr_dataoffset == sizeof(struct attrreference));
+      if (0 < nameAttr.attrRef.attr_length)
+        RealPath->append(nameAttr.Name,
+                         nameAttr.Name + nameAttr.attrRef.attr_length - 1);
+    }
+  #elif defined(F_GETPATH)
----------------
Please remember to remove code which is disabled if you check it in.

================
Comment at: lib/Support/Unix/Path.inc:554-556
@@ +553,5 @@
+      RealPath->append(Buffer, Buffer + strlen(Buffer));
+  #else
+    // If we have a /proc filesystem mounted, we ca quickly establish the
+    // real name of the file with readlink
+    static const bool HasProc = (0 == ::access("/proc/self/fd", R_OK));
----------------
This should be `#ifdef __linux__`

================
Comment at: lib/Support/Unix/Path.inc:557
@@ +556,3 @@
+    // real name of the file with readlink
+    static const bool HasProc = (0 == ::access("/proc/self/fd", R_OK));
+    char Buffer[PATH_MAX];
----------------
I wouldn't bother with this, it has a non-trivial amount of overhead on non-X86 platforms.  I'd just fall-back to `::realpath` if `::readlink` failed.

In fact, why not fall back to `::realpath` regardless of platform?

================
Comment at: lib/Support/Unix/Path.inc:560-561
@@ +559,4 @@
+    if (HasProc) {
+      char ProcPath[64];
+      int N = snprintf(ProcPath, sizeof(ProcPath), "/proc/self/fd/%d", ResultFD);
+      assert(N > 0 && N < sizeof(ProcPath));
----------------
I think it'd be nicer to build a twine like so:
  SmallString<32> ProcPathStorage;
  StringRef ProcPath = Twine("/proc/self/fd/").concat(ResultFD).toNullTerminatedStringRef(ProcPathStorage);

================
Comment at: lib/Support/Unix/Path.inc:563-565
@@ +562,5 @@
+      assert(N > 0 && N < sizeof(ProcPath));
+      ssize_t CharCount = ::readlink(ProcPath, Buffer, sizeof(Buffer));
+      if (CharCount > 0)
+        RealPath->append(Buffer, Buffer + CharCount);
+    } else {
----------------
What's the contract on failure?  Should `RealPath` be cleared?

================
Comment at: lib/Support/Windows/Path.inc:701
@@ +700,3 @@
+    DWORD CountChars =
+      ::GetFinalPathNameByHandleW(H, RealPathUTF16, MAX_PATH, 0);
+    if (CountChars > 0 && CountChars < MAX_PATH) {
----------------
Could we use `FILE_NAME_NORMALIZED` instead of `0`?

================
Comment at: lib/Support/Windows/Path.inc:702
@@ +701,3 @@
+      ::GetFinalPathNameByHandleW(H, RealPathUTF16, MAX_PATH, 0);
+    if (CountChars > 0 && CountChars < MAX_PATH) {
+      // Convert the result from UTF-16 to UTF-8.
----------------
Seeing as how we support extended-length paths, it'd be nice to continue supporting them here.  Perhaps we could retry similarly to what we do in `Process::GetEnv` ?

================
Comment at: lib/Support/Windows/Path.inc:704
@@ +703,3 @@
+      // Convert the result from UTF-16 to UTF-8.
+      SmallVector<char, MAX_PATH> RealPathUTF8;
+      if (!UTF16ToUTF8(RealPathUTF16, CountChars, RealPathUTF8))
----------------
I'd use `SmallString<MAX_PATH> RealPathUTF8;`


http://reviews.llvm.org/D19842





More information about the llvm-commits mailing list