Change-Id: I4d5a0bebeeefc35dac0bbc065c104c70c24aae17
This commit is contained in:
Jade Lovelace
2025-12-11 14:35:33 -08:00
parent 6f483e5f52
commit 9b8d10daa7
+49 -3
View File
@@ -1,9 +1,11 @@
#include <archive.h>
#include <archive_entry.h>
#include <kj/async.h>
#include <map>
#include "async-io.hh"
#include "file-descriptor.hh"
#include "lix/libstore/temporary-dir.hh"
#include "lix/libutil/c-calls.hh"
#include "lix/libutil/charptr-cast.hh"
#include "lix/libutil/file-system.hh"
@@ -86,13 +88,57 @@ void TarArchive::close()
check(archive_read_close(this->archive.get()), "Failed to close archive (%s)");
}
namespace {
struct IndexEntry
{
struct IndexDirectory
{
std::map<std::string, IndexEntry> entries;
};
struct IndexFile
{
uint64_t start;
uint64_t size;
};
std::variant<IndexDirectory, IndexFile> innerData;
int mode;
};
/** Extract a TAR archive into an in-memory index with data stored on disk,
* because fundamentally all we have to do when importing archives to the store
* is to sort the entries and then send it into a NAR serializer.
*
* This deals with macOS performance problems by not materializing the files to
* disk in the first place.
*
* https://git.lix.systems/lix-project/lix/issues/1072
*/
struct InMemoryIndex
{
Path tempDir;
AutoDelete tempDirDeleter;
AutoCloseFD backingFile;
std::ofstream writer;
IndexEntry topLevel;
InMemoryIndex() : tempDir(createTempDir()), tempDirDeleter(tempDir, true)
{
backingFile = sys::open(tempDir + "/extracted", O_RDWR | O_TRUNC | O_CLOEXEC);
}
};
}
static void extract_archive(TarArchive & archive, const Path & destDir)
{
requireCString(destDir);
int flags = ARCHIVE_EXTRACT_TIME
| ARCHIVE_EXTRACT_SECURE_SYMLINKS
| ARCHIVE_EXTRACT_SECURE_NODOTDOT;
int flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_SECURE_SYMLINKS
| ARCHIVE_EXTRACT_SECURE_NODOTDOT | ARCHIVE_EXTRACT_NO_HFS_COMPRESSION;
for (;;) {
struct archive_entry * entry;