summaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/Support/TarWriter.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-20 14:16:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-20 14:16:56 +0000
commit2cab237b5dbfe1b3e9c7aa7a3c02d2b98fcf7462 (patch)
tree524fe828571f81358bba62fdb6d04c6e5e96a2a4 /contrib/llvm/lib/Support/TarWriter.cpp
parent6c7828a2807ea5e50c79ca42dbedf2b589ce63b2 (diff)
parent044eb2f6afba375a914ac9d8024f8f5142bb912e (diff)
Notes
Diffstat (limited to 'contrib/llvm/lib/Support/TarWriter.cpp')
-rw-r--r--contrib/llvm/lib/Support/TarWriter.cpp62
1 files changed, 36 insertions, 26 deletions
diff --git a/contrib/llvm/lib/Support/TarWriter.cpp b/contrib/llvm/lib/Support/TarWriter.cpp
index f06abf46cce4..abc46d076576 100644
--- a/contrib/llvm/lib/Support/TarWriter.cpp
+++ b/contrib/llvm/lib/Support/TarWriter.cpp
@@ -116,34 +116,37 @@ 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};
+// Path fits in a Ustar header if
+//
+// - Path is less than 100 characters long, or
+// - Path is in the form of "<prefix>/<name>" where <prefix> is less
+// than or equal to 155 characters long and <name> is less than 100
+// characters long. Both <prefix> and <name> can contain extra '/'.
+//
+// If Path fits in a Ustar header, updates Prefix and Name and returns true.
+// Otherwise, returns false.
+static bool splitUstar(StringRef Path, StringRef &Prefix, StringRef &Name) {
+ if (Path.size() < sizeof(UstarHeader::Name)) {
+ Prefix = "";
+ Name = Path;
+ return true;
+ }
+
size_t Sep = Path.rfind('/', sizeof(UstarHeader::Prefix) + 1);
if (Sep == StringRef::npos)
- return {"", Path};
- return {Path.substr(0, Sep), Path.substr(Sep + 1)};
-}
+ return false;
+ if (Path.size() - Sep - 1 >= sizeof(UstarHeader::Name))
+ return false;
-// Returns true if a given path can be stored to a Ustar header
-// without the PAX extension.
-static bool fitsInUstar(StringRef Path) {
- StringRef Prefix;
- StringRef Name;
- std::tie(Prefix, Name) = splitPath(Path);
- return Name.size() <= sizeof(UstarHeader::Name);
+ Prefix = Path.substr(0, Sep);
+ Name = Path.substr(Sep + 1);
+ return true;
}
// 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);
-
+static void writeUstarHeader(raw_fd_ostream &OS, StringRef Prefix,
+ StringRef Name, size_t Size) {
UstarHeader Hdr = makeUstarHeader();
memcpy(Hdr.Name, Name.data(), Name.size());
memcpy(Hdr.Mode, "0000664", 8);
@@ -168,12 +171,19 @@ TarWriter::TarWriter(int FD, StringRef BaseDir)
// Append a given file to an archive.
void TarWriter::append(StringRef Path, StringRef Data) {
// Write Path and Data.
- std::string S = BaseDir + "/" + sys::path::convert_to_slash(Path) + "\0";
- if (fitsInUstar(S)) {
- writeUstarHeader(OS, S, Data.size());
+ std::string Fullpath = BaseDir + "/" + sys::path::convert_to_slash(Path);
+
+ // We do not want to include the same file more than once.
+ if (!Files.insert(Fullpath).second)
+ return;
+
+ StringRef Prefix;
+ StringRef Name;
+ if (splitUstar(Fullpath, Prefix, Name)) {
+ writeUstarHeader(OS, Prefix, Name, Data.size());
} else {
- writePaxHeader(OS, S);
- writeUstarHeader(OS, "", Data.size());
+ writePaxHeader(OS, Fullpath);
+ writeUstarHeader(OS, "", "", Data.size());
}
OS << Data;