1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-05 20:41:47 +02:00

Support hard links in tarballs

Fixes #10395.
This commit is contained in:
Eelco Dolstra 2024-06-11 16:05:57 +02:00
parent d1dd7abbf0
commit 35bdb9cee7
7 changed files with 78 additions and 7 deletions

View file

@ -41,6 +41,19 @@ struct FileSystemObjectSink
virtual void createSymlink(const Path & path, const std::string & target) = 0;
};
/**
* An extension of `FileSystemObjectSink` that supports file types
* that are not supported by Nix's FSO model.
*/
struct ExtendedFileSystemObjectSink : FileSystemObjectSink
{
/**
* Create a hard link. The target must be the path of a previously
* encountered file relative to the root of the FSO.
*/
virtual void createHardlink(const Path & path, const CanonPath & target) = 0;
};
/**
* Recursively copy file system objects from the source into the sink.
*/

View file

@ -163,7 +163,7 @@ void unpackTarfile(const Path & tarFile, const Path & destDir)
extract_archive(archive, destDir);
}
time_t unpackTarfileToSink(TarArchive & archive, FileSystemObjectSink & parseSink)
time_t unpackTarfileToSink(TarArchive & archive, ExtendedFileSystemObjectSink & parseSink)
{
time_t lastModified = 0;
@ -183,7 +183,12 @@ time_t unpackTarfileToSink(TarArchive & archive, FileSystemObjectSink & parseSin
lastModified = std::max(lastModified, archive_entry_mtime(entry));
switch (archive_entry_filetype(entry)) {
if (auto target = archive_entry_hardlink(entry)) {
parseSink.createHardlink(path, CanonPath(target));
continue;
}
switch (auto type = archive_entry_filetype(entry)) {
case AE_IFDIR:
parseSink.createDirectory(path);
@ -220,7 +225,7 @@ time_t unpackTarfileToSink(TarArchive & archive, FileSystemObjectSink & parseSin
}
default:
throw Error("file '%s' in tarball has unsupported file type", path);
throw Error("file '%s' in tarball has unsupported file type %d", path, type);
}
}

View file

@ -41,6 +41,6 @@ void unpackTarfile(Source & source, const Path & destDir);
void unpackTarfile(const Path & tarFile, const Path & destDir);
time_t unpackTarfileToSink(TarArchive & archive, FileSystemObjectSink & parseSink);
time_t unpackTarfileToSink(TarArchive & archive, ExtendedFileSystemObjectSink & parseSink);
}