summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Support
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2017-01-07 08:28:56 +0000
committerRui Ueyama <ruiu@google.com>2017-01-07 08:28:56 +0000
commit999f094aa3ccda4708fd7290f44cb9ae68666e54 (patch)
tree40c172b92044902ee2dd23f5c6a17fc3f94db570 /llvm/lib/Support
parent3f499b68259155d53e7e65f2d95e1e9148242d2b (diff)
downloadbcm5719-llvm-999f094aa3ccda4708fd7290f44cb9ae68666e54.tar.gz
bcm5719-llvm-999f094aa3ccda4708fd7290f44cb9ae68666e54.zip
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. llvm-svn: 291340
Diffstat (limited to 'llvm/lib/Support')
-rw-r--r--llvm/lib/Support/TarWriter.cpp28
1 files changed, 27 insertions, 1 deletions
diff --git a/llvm/lib/Support/TarWriter.cpp b/llvm/lib/Support/TarWriter.cpp
index 5fc17d27637..5e45b36771f 100644
--- a/llvm/lib/Support/TarWriter.cpp
+++ b/llvm/lib/Support/TarWriter.cpp
@@ -109,14 +109,40 @@ static void writePaxHeader(raw_fd_ostream &OS, StringRef Path) {
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));
}
OpenPOWER on IntegriCloud