//===-- TarWriter.cpp - Tar archive file creator --------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // TarWriter class provides a feature to create a tar archive file. // // I put emphasis on simplicity over comprehensiveness when implementing this // class because we don't need a full-fledged archive file generator in LLVM // at the moment. // // The filename field in the Unix V7 tar header is 100 bytes. Longer filenames // are stored using the PAX extension. The PAX header is standardized in // POSIX.1-2001. // // The struct definition of UstarHeader is copied from // https://www.freebsd.org/cgi/man.cgi?query=tar&sektion=5 // //===----------------------------------------------------------------------===// #include "llvm/Support/TarWriter.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" usingnamespacellvm; // Each file in an archive must be aligned to this block size. static const int BlockSize = …; struct UstarHeader { … }; static_assert …; static UstarHeader makeUstarHeader() { … } // A PAX attribute is in the form of "<length> <key>=<value>\n" // where <length> is the length of the entire string including // the length field itself. An example string is this. // // 25 ctime=1084839148.1212\n // // This function create such string. static std::string formatPax(StringRef Key, StringRef Val) { … } // Headers in tar files must be aligned to 512 byte boundaries. // This function forwards the current file position to the next boundary. static void pad(raw_fd_ostream &OS) { … } // Computes a checksum for a tar header. static void computeChecksum(UstarHeader &Hdr) { … } // Create a tar header and write it to a given output stream. static void writePaxHeader(raw_fd_ostream &OS, StringRef 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) { … } // 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 Prefix, StringRef Name, size_t Size) { … } // Creates a TarWriter instance and returns it. Expected<std::unique_ptr<TarWriter>> TarWriter::create(StringRef OutputPath, StringRef BaseDir) { … } TarWriter::TarWriter(int FD, StringRef BaseDir) : … { … } // Append a given file to an archive. void TarWriter::append(StringRef Path, StringRef Data) { … }