[llvm] r291340 - TarWriter: Use Ustar header's "prefix" field to store long filenames.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 7 00:28:56 PST 2017


Author: ruiu
Date: Sat Jan  7 02:28:56 2017
New Revision: 291340

URL: http://llvm.org/viewvc/llvm-project?rev=291340&view=rev
Log:
TarWriter: Use Ustar header's "prefix" field to store long filenames.

Tar's Ustar header has the "prefix" field to store a directory
part of a filename. It is not as flexible as the PAX-extended
filename because there's still a limitation on the maximum filename
size, but it mitigates the situation.

This patch should unbreak some Windows buildbots that uses very
old tar command.

Modified:
    llvm/trunk/lib/Support/TarWriter.cpp

Modified: llvm/trunk/lib/Support/TarWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/TarWriter.cpp?rev=291340&r1=291339&r2=291340&view=diff
==============================================================================
--- llvm/trunk/lib/Support/TarWriter.cpp (original)
+++ llvm/trunk/lib/Support/TarWriter.cpp Sat Jan  7 02:28:56 2017
@@ -109,14 +109,40 @@ static void writePaxHeader(raw_fd_ostrea
   pad(OS);
 }
 
+// In the Ustar header, a path can be split at any '/' to store
+// a path into UstarHeader::Name and UstarHeader::Prefix. This
+// function splits a given path for that purpose.
+static std::pair<StringRef, StringRef> splitPath(StringRef Path) {
+  if (Path.size() <= sizeof(UstarHeader::Name))
+    return {"", Path};
+  size_t Sep = Path.rfind('/', sizeof(UstarHeader::Name) + 1);
+  if (Sep == StringRef::npos)
+    return {"", Path};
+  return {Path.substr(0, Sep), Path.substr(Sep + 1)};
+}
+
+// Returns true if a given path can be stored to a Ustar header
+// without the PAX extension.
+static bool fitInUstar(StringRef Path) {
+  StringRef Prefix;
+  StringRef Name;
+  std::tie(Prefix, Name) = splitPath(Path);
+  return Name.size() <= sizeof(UstarHeader::Name);
+}
+
 // The PAX header is an extended format, so a PAX header needs
 // to be followed by a "real" header.
 static void writeUstarHeader(raw_fd_ostream &OS, StringRef Path, size_t Size) {
+  StringRef Prefix;
+  StringRef Name;
+  std::tie(Prefix, Name) = splitPath(Path);
+
   UstarHeader Hdr = {};
-  memcpy(Hdr.Name, Path.data(), Path.size());
+  memcpy(Hdr.Name, Name.data(), Name.size());
   memcpy(Hdr.Mode, "0000664", 8);
   snprintf(Hdr.Size, sizeof(Hdr.Size), "%011zo", Size);
   memcpy(Hdr.Magic, "ustar", 6);
+  memcpy(Hdr.Prefix, Prefix.data(), Prefix.size());
   computeChecksum(Hdr);
   OS << StringRef(reinterpret_cast<char *>(&Hdr), sizeof(Hdr));
 }




More information about the llvm-commits mailing list