public void SetsLastModifiedTimeOnExtractedFiles() { using TempDirectory root = new TempDirectory(); string inDir = Path.Join(root.Path, "indir"); string inFile = Path.Join(inDir, "file"); string tarFile = Path.Join(root.Path, "file.tar"); string outDir = Path.Join(root.Path, "outdir"); string outFile = Path.Join(outDir, "file"); Directory.CreateDirectory(inDir); File.Create(inFile).Dispose(); var dt = new DateTime(2001, 1, 2, 3, 4, 5, DateTimeKind.Local); File.SetLastWriteTime(inFile, dt); TarFile.CreateFromDirectory(sourceDirectoryName: inDir, destinationFileName: tarFile, includeBaseDirectory: false); Directory.CreateDirectory(outDir); TarFile.ExtractToDirectory(sourceFileName: tarFile, destinationDirectoryName: outDir, overwriteFiles: false); Assert.True(File.Exists(outFile)); Assert.InRange(File.GetLastWriteTime(outFile).Ticks, dt.AddSeconds(-3).Ticks, dt.AddSeconds(3).Ticks); // include some slop for filesystem granularity }
/// <summary> /// Initializes a new instance of the VirtualMachine class. /// </summary> /// <param name="fileStream">The stream containing the .XVA file.</param> /// <param name="ownership">Whether to transfer ownership of <c>fileStream</c> to the new instance.</param> public VirtualMachine(Stream fileStream, Ownership ownership) { _fileStream = fileStream; _ownership = ownership; _fileStream.Position = 0; _archive = new TarFile(fileStream); }
public override ILoadedImage Load(Address?addrLoad) { var rdr = new ByteImageReader(base.RawImage); var archive = new TarArchive(this.ImageLocation); for (; ;) { var tarHeader = rdr.ReadStruct <tar_header>(); if (tarHeader.filename.All(b => b == 0)) { break; } if (PeekString(rdr, "ustar")) { var ustarHeader = rdr.ReadStruct <ustar_header>(); Align(rdr, TarBlockSize); var filename = TarFile.GetString(tarHeader.filename); var file = archive.AddFile(filename, (a, p, n) => TarFile.Load(a, p, n, tarHeader, ustarHeader, rdr)); rdr.Offset += file.Length; Align(rdr, TarBlockSize); } } return(archive); }
public async Task UnixFileModes_RestrictiveParentDir_Async() { using TempDirectory source = new TempDirectory(); using TempDirectory destination = new TempDirectory(); string archivePath = Path.Join(source.Path, "archive.tar"); using FileStream archiveStream = File.Create(archivePath); using (TarWriter writer = new TarWriter(archiveStream)) { PaxTarEntry dir = new PaxTarEntry(TarEntryType.Directory, "dir"); dir.Mode = UnixFileMode.None; // Restrict permissions. writer.WriteEntry(dir); PaxTarEntry file = new PaxTarEntry(TarEntryType.RegularFile, "dir/file"); file.Mode = TestPermission1; writer.WriteEntry(file); } await TarFile.ExtractToDirectoryAsync(archivePath, destination.Path, overwriteFiles : false); string dirPath = Path.Join(destination.Path, "dir"); Assert.True(Directory.Exists(dirPath), $"{dirPath}' does not exist."); AssertFileModeEquals(dirPath, UnixFileMode.None); // Set dir permissions so we can access file. SetUnixFileMode(dirPath, UserAll); string filePath = Path.Join(dirPath, "file"); Assert.True(File.Exists(filePath), $"{filePath}' does not exist."); AssertFileModeEquals(filePath, TestPermission1); }
// This test would not pass for the V7 and Ustar formats in some OSs like MacCatalyst, tvOSSimulator and OSX, because the TempDirectory gets created in // a folder with a path longer than 100 bytes, and those tar formats have no way of handling pathnames and linknames longer than that length. // The rest of the OSs create the TempDirectory in a path that does not surpass the 100 bytes, so the 'subfolder' parameter gives a chance to extend // the base directory past that length, to ensure this scenario is tested everywhere. private async Task Extract_LinkEntry_TargetInsideDirectory_Internal_Async(TarEntryType entryType, TarEntryFormat format, string subfolder) { using (TempDirectory root = new TempDirectory()) { string baseDir = string.IsNullOrEmpty(subfolder) ? root.Path : Path.Join(root.Path, subfolder); Directory.CreateDirectory(baseDir); string linkName = "link"; string targetName = "target"; string targetPath = Path.Join(baseDir, targetName); File.Create(targetPath).Dispose(); await using (MemoryStream archive = new MemoryStream()) { await using (TarWriter writer = new TarWriter(archive, format, leaveOpen: true)) { TarEntry entry = InvokeTarEntryCreationConstructor(format, entryType, linkName); entry.LinkName = targetPath; await writer.WriteEntryAsync(entry); } archive.Seek(0, SeekOrigin.Begin); await TarFile.ExtractToDirectoryAsync(archive, baseDir, overwriteFiles : false); Assert.Equal(2, Directory.GetFileSystemEntries(baseDir).Count()); } } }
public void ReadTarFileTest() { using (Stream stream = File.OpenRead("Deb/libplist3_1.12-3.1_amd64.deb")) using (ArFile arFile = new ArFile(stream, leaveOpen: true)) { // Skip the debian version arFile.Read(); // This is the tar file arFile.Read(); Collection <string> filenames = new Collection <string>(); Collection <string> contents = new Collection <string>(); Collection <TarHeader> headers = new Collection <TarHeader>(); using (Stream entryStream = arFile.Open()) using (GZipDecompressor decompressedStream = new GZipDecompressor(entryStream, leaveOpen: true)) using (TarFile tarFile = new TarFile(decompressedStream, leaveOpen: true)) { while (tarFile.Read()) { filenames.Add(tarFile.FileName); headers.Add((TarHeader)tarFile.FileHeader); using (Stream data = tarFile.Open()) using (StreamReader reader = new StreamReader(data)) { contents.Add(reader.ReadToEnd()); } } } } }
public Task ExtractToDirectoryAsync_Cancel() { CancellationTokenSource cs = new CancellationTokenSource(); cs.Cancel(); return(Assert.ThrowsAsync <TaskCanceledException>(() => TarFile.ExtractToDirectoryAsync("file.tar", "directory", overwriteFiles: true, cs.Token))); }
public void ExtractEntry_ManySubfolderSegments_NoPrecedingDirectoryEntries() { using TempDirectory root = new TempDirectory(); string firstSegment = "a"; string secondSegment = Path.Join(firstSegment, "b"); string fileWithTwoSegments = Path.Join(secondSegment, "c.txt"); using MemoryStream archive = new MemoryStream(); using (TarWriter writer = new TarWriter(archive, TarFormat.Ustar, leaveOpen: true)) { // No preceding directory entries for the segments UstarTarEntry entry = new UstarTarEntry(TarEntryType.RegularFile, fileWithTwoSegments); entry.DataStream = new MemoryStream(); entry.DataStream.Write(new byte[] { 0x1 }); entry.DataStream.Seek(0, SeekOrigin.Begin); writer.WriteEntry(entry); } archive.Seek(0, SeekOrigin.Begin); TarFile.ExtractToDirectory(archive, root.Path, overwriteFiles: false); Assert.True(Directory.Exists(Path.Join(root.Path, firstSegment))); Assert.True(Directory.Exists(Path.Join(root.Path, secondSegment))); Assert.True(File.Exists(Path.Join(root.Path, fileWithTwoSegments))); }
public void Extract_AllSegmentsOfPath() { using TempDirectory source = new TempDirectory(); using TempDirectory destination = new TempDirectory(); string archivePath = Path.Join(source.Path, "archive.tar"); using FileStream archiveStream = File.Create(archivePath); using (TarWriter writer = new TarWriter(archiveStream)) { PaxTarEntry segment1 = new PaxTarEntry(TarEntryType.Directory, "segment1"); writer.WriteEntry(segment1); PaxTarEntry segment2 = new PaxTarEntry(TarEntryType.Directory, "segment1/segment2"); writer.WriteEntry(segment2); PaxTarEntry file = new PaxTarEntry(TarEntryType.RegularFile, "segment1/segment2/file.txt"); writer.WriteEntry(file); } TarFile.ExtractToDirectory(archivePath, destination.Path, overwriteFiles: false); string segment1Path = Path.Join(destination.Path, "segment1"); Assert.True(Directory.Exists(segment1Path), $"{segment1Path}' does not exist."); string segment2Path = Path.Join(segment1Path, "segment2"); Assert.True(Directory.Exists(segment2Path), $"{segment2Path}' does not exist."); string filePath = Path.Join(segment2Path, "file.txt"); Assert.True(File.Exists(filePath), $"{filePath}' does not exist."); }
public async Task NullStream_Throws_Async() { await using (MemoryStream archiveStream = new MemoryStream()) { await Assert.ThrowsAsync <ArgumentNullException>(() => TarFile.CreateFromDirectoryAsync(sourceDirectoryName: "path", destination: null, includeBaseDirectory: false)); } }
public void Extract_Archive_File_OverwriteTrue() { string testCaseName = "file"; string archivePath = GetTarFilePath(CompressionMethod.Uncompressed, TestTarFormat.pax, testCaseName); using TempDirectory destination = new TempDirectory(); string filePath = Path.Join(destination.Path, "file.txt"); using (FileStream fileStream = File.Create(filePath)) { using StreamWriter writer = new StreamWriter(fileStream, leaveOpen: false); writer.WriteLine("Original text"); } TarFile.ExtractToDirectory(archivePath, destination.Path, overwriteFiles: true); Assert.True(File.Exists(filePath)); using (FileStream fileStream = File.Open(filePath, FileMode.Open)) { using StreamReader reader = new StreamReader(fileStream); string actualContents = reader.ReadLine(); Assert.Equal($"Hello {testCaseName}", actualContents); // Confirm overwrite } }
public void InvalidPaths_Throw() { Assert.Throws <ArgumentNullException>(() => TarFile.CreateFromDirectory(sourceDirectoryName: null, destinationFileName: "path", includeBaseDirectory: false)); Assert.Throws <ArgumentException>(() => TarFile.CreateFromDirectory(sourceDirectoryName: string.Empty, destinationFileName: "path", includeBaseDirectory: false)); Assert.Throws <ArgumentNullException>(() => TarFile.CreateFromDirectory(sourceDirectoryName: "path", destinationFileName: null, includeBaseDirectory: false)); Assert.Throws <ArgumentException>(() => TarFile.CreateFromDirectory(sourceDirectoryName: "path", destinationFileName: string.Empty, includeBaseDirectory: false)); }
public void WriteTarFileTest() { using (Stream original = File.OpenRead(@"IO/test.tar")) using (Stream expected = File.OpenRead(@"IO/test.tar")) using (Stream actual = new MemoryStream()) using (Stream output = new ValidatingCompositeStream(null, actual, expected)) { var tar = new TarFile(original, true); while (tar.Read()) { Stream data = new MemoryStream(); if (tar.FileHeader.FileMode == LinuxFileMode.S_IFDIR) { tar.Skip(); } else { data = tar.Open(); } var clonedHeader = this.CloneHeader((TarHeader)tar.FileHeader); this.AssertCompareClonedHeader((TarHeader)tar.FileHeader, clonedHeader); using (data) { TarFileCreator.WriteEntry(output, this.CloneHeader(clonedHeader), data); } } TarFileCreator.WriteTrailer(output); } }
public void SkipRecursionIntoBaseDirectorySymlink() { using TempDirectory root = new TempDirectory(); string destinationArchive = Path.Join(root.Path, "destination.tar"); string externalDirectory = Path.Join(root.Path, "externalDirectory"); Directory.CreateDirectory(externalDirectory); string subDirectory = Path.Join(externalDirectory, "subDirectory"); Directory.CreateDirectory(subDirectory); string sourceDirectoryName = Path.Join(root.Path, "baseDirectory"); Directory.CreateSymbolicLink(sourceDirectoryName, externalDirectory); TarFile.CreateFromDirectory(sourceDirectoryName, destinationArchive, includeBaseDirectory: true); // Base directory is a symlink, do not recurse using FileStream archiveStream = File.OpenRead(destinationArchive); using TarReader reader = new(archiveStream, leaveOpen : false); TarEntry entry = reader.GetNextEntry(); Assert.NotNull(entry); Assert.Equal("baseDirectory/", entry.Name); Assert.Equal(TarEntryType.SymbolicLink, entry.EntryType); Assert.Null(reader.GetNextEntry()); }
public void SkipRecursionIntoDirectorySymlinks() { using TempDirectory root = new TempDirectory(); string destinationArchive = Path.Join(root.Path, "destination.tar"); string externalDirectory = Path.Join(root.Path, "externalDirectory"); Directory.CreateDirectory(externalDirectory); File.Create(Path.Join(externalDirectory, "file.txt")).Dispose(); string sourceDirectoryName = Path.Join(root.Path, "baseDirectory"); Directory.CreateDirectory(sourceDirectoryName); string subDirectory = Path.Join(sourceDirectoryName, "subDirectory"); Directory.CreateSymbolicLink(subDirectory, externalDirectory); // Should not recurse here TarFile.CreateFromDirectory(sourceDirectoryName, destinationArchive, includeBaseDirectory: false); using FileStream archiveStream = File.OpenRead(destinationArchive); using TarReader reader = new(archiveStream, leaveOpen : false); TarEntry entry = reader.GetNextEntry(); Assert.NotNull(entry); Assert.Equal("subDirectory/", entry.Name); Assert.Equal(TarEntryType.SymbolicLink, entry.EntryType); Assert.Null(reader.GetNextEntry()); // file.txt should not be found }
public async Task IncludeBaseDirectoryIfEmpty_Async() { using (TempDirectory source = new TempDirectory()) using (TempDirectory destination = new TempDirectory()) { string destinationArchiveFileName = Path.Join(destination.Path, "output.tar"); await TarFile.CreateFromDirectoryAsync(source.Path, destinationArchiveFileName, includeBaseDirectory : true); FileStreamOptions readOptions = new() { Access = FileAccess.Read, Mode = FileMode.Open, Options = FileOptions.Asynchronous, }; await using (FileStream fileStream = File.Open(destinationArchiveFileName, readOptions)) { await using (TarReader reader = new TarReader(fileStream)) { TarEntry entry = await reader.GetNextEntryAsync(); Assert.NotNull(entry); Assert.Equal(TarEntryType.Directory, entry.EntryType); Assert.Equal(Path.GetFileName(source.Path) + '/', entry.Name); Assert.Null(await reader.GetNextEntryAsync()); } } } }
public Task CreateFromDirectoryAsync_Cancel() { CancellationTokenSource cs = new CancellationTokenSource(); cs.Cancel(); return(Assert.ThrowsAsync <TaskCanceledException>(() => TarFile.CreateFromDirectoryAsync("directory", "file.tar", includeBaseDirectory: false, cs.Token))); }
public void InvalidPaths_Throw() { Assert.Throws <ArgumentNullException>(() => TarFile.ExtractToDirectory(sourceFileName: null, destinationDirectoryName: "path", overwriteFiles: false)); Assert.Throws <ArgumentException>(() => TarFile.ExtractToDirectory(sourceFileName: string.Empty, destinationDirectoryName: "path", overwriteFiles: false)); Assert.Throws <ArgumentNullException>(() => TarFile.ExtractToDirectory(sourceFileName: "path", destinationDirectoryName: null, overwriteFiles: false)); Assert.Throws <ArgumentException>(() => TarFile.ExtractToDirectory(sourceFileName: "path", destinationDirectoryName: string.Empty, overwriteFiles: false)); }
public async Task Extract_UnseekableStream_BlockAlignmentPadding_DoesNotAffectNextEntries_Async(int contentSize) { byte[] fileContents = new byte[contentSize]; Array.Fill <byte>(fileContents, 0x1); using var archive = new MemoryStream(); using (var compressor = new GZipStream(archive, CompressionMode.Compress, leaveOpen: true)) { using var writer = new TarWriter(compressor); var entry1 = new PaxTarEntry(TarEntryType.RegularFile, "file"); entry1.DataStream = new MemoryStream(fileContents); await writer.WriteEntryAsync(entry1); var entry2 = new PaxTarEntry(TarEntryType.RegularFile, "next-file"); await writer.WriteEntryAsync(entry2); } archive.Position = 0; using var decompressor = new GZipStream(archive, CompressionMode.Decompress); using var reader = new TarReader(decompressor); using TempDirectory destination = new TempDirectory(); await TarFile.ExtractToDirectoryAsync(decompressor, destination.Path, overwriteFiles : true); Assert.Equal(2, Directory.GetFileSystemEntries(destination.Path, "*", SearchOption.AllDirectories).Count()); }
public void VerifyIncludeBaseDirectory(bool includeBaseDirectory) { using TempDirectory source = new TempDirectory(); using TempDirectory destination = new TempDirectory(); string fileName1 = "file1.txt"; string filePath1 = Path.Join(source.Path, fileName1); File.Create(filePath1).Dispose(); string subDirectoryName = "dir/"; // The trailing separator is preserved in the TarEntry.Name string subDirectoryPath = Path.Join(source.Path, subDirectoryName); Directory.CreateDirectory(subDirectoryPath); string fileName2 = "file2.txt"; string filePath2 = Path.Join(subDirectoryPath, fileName2); File.Create(filePath2).Dispose(); string destinationArchiveFileName = Path.Join(destination.Path, "output.tar"); TarFile.CreateFromDirectory(source.Path, destinationArchiveFileName, includeBaseDirectory); using FileStream fileStream = File.OpenRead(destinationArchiveFileName); using TarReader reader = new TarReader(fileStream); List <TarEntry> entries = new List <TarEntry>(); TarEntry entry; while ((entry = reader.GetNextEntry()) != null) { entries.Add(entry); } Assert.Equal(3, entries.Count); string prefix = includeBaseDirectory ? Path.GetFileName(source.Path) + '/' : string.Empty; TarEntry entry1 = entries.FirstOrDefault(x => x.EntryType == TarEntryType.RegularFile && x.Name == prefix + fileName1); Assert.NotNull(entry1); TarEntry directory = entries.FirstOrDefault(x => x.EntryType == TarEntryType.Directory && x.Name == prefix + subDirectoryName); Assert.NotNull(directory); string actualFileName2 = subDirectoryName + fileName2; // Notice the trailing separator in subDirectoryName TarEntry entry2 = entries.FirstOrDefault(x => x.EntryType == TarEntryType.RegularFile && x.Name == prefix + actualFileName2); Assert.NotNull(entry2); }
public void NonExistentDirectory_Throws() { using TempDirectory root = new TempDirectory(); string dirPath = Path.Join(root.Path, "dir"); using MemoryStream archive = new MemoryStream(); Assert.Throws <DirectoryNotFoundException>(() => TarFile.CreateFromDirectory(sourceDirectoryName: dirPath, destination: archive, includeBaseDirectory: false)); }
public void NonExistentDirectory_Throws() { using TempDirectory root = new TempDirectory(); string dirPath = Path.Join(root.Path, "dir"); using MemoryStream archive = new MemoryStream(); Assert.Throws <DirectoryNotFoundException>(() => TarFile.ExtractToDirectory(archive, destinationDirectoryName: dirPath, overwriteFiles: false)); }
public async Task InvalidPath_Throws_Async() { using (MemoryStream archive = new MemoryStream()) { await Assert.ThrowsAsync <ArgumentNullException>(() => TarFile.ExtractToDirectoryAsync(archive, destinationDirectoryName: null, overwriteFiles: false)); await Assert.ThrowsAsync <ArgumentException>(() => TarFile.ExtractToDirectoryAsync(archive, destinationDirectoryName: string.Empty, overwriteFiles: false)); } }
public void NonExistentDirectory_Throws() { using TempDirectory root = new TempDirectory(); string dirPath = Path.Join(root.Path, "dir"); string filePath = Path.Join(root.Path, "file.tar"); Assert.Throws <DirectoryNotFoundException>(() => TarFile.CreateFromDirectory(sourceDirectoryName: "IDontExist", destinationFileName: filePath, includeBaseDirectory: false)); }
public async Task InvalidPath_Throws_Async() { await using (MemoryStream archiveStream = new MemoryStream()) { await Assert.ThrowsAsync <ArgumentNullException>(() => TarFile.CreateFromDirectoryAsync(sourceDirectoryName: null, destination: archiveStream, includeBaseDirectory: false)); await Assert.ThrowsAsync <ArgumentException>(() => TarFile.CreateFromDirectoryAsync(sourceDirectoryName: string.Empty, destination: archiveStream, includeBaseDirectory: false)); } }
public async Task InvalidPaths_Throw_Async() { await Assert.ThrowsAsync <ArgumentNullException>(() => TarFile.CreateFromDirectoryAsync(sourceDirectoryName: null, destinationFileName: "path", includeBaseDirectory: false)); await Assert.ThrowsAsync <ArgumentException>(() => TarFile.CreateFromDirectoryAsync(sourceDirectoryName: string.Empty, destinationFileName: "path", includeBaseDirectory: false)); await Assert.ThrowsAsync <ArgumentNullException>(() => TarFile.CreateFromDirectoryAsync(sourceDirectoryName: "path", destinationFileName: null, includeBaseDirectory: false)); await Assert.ThrowsAsync <ArgumentException>(() => TarFile.CreateFromDirectoryAsync(sourceDirectoryName: "path", destinationFileName: string.Empty, includeBaseDirectory: false)); }
public async Task NonExistentDirectory_Throws_Async() { using (TempDirectory root = new TempDirectory()) { string dirPath = Path.Join(root.Path, "dir"); string filePath = Path.Join(root.Path, "file.tar"); await Assert.ThrowsAsync <DirectoryNotFoundException>(() => TarFile.CreateFromDirectoryAsync(sourceDirectoryName: "IDontExist", destinationFileName: filePath, includeBaseDirectory: false)); } }
public async Task InvalidPaths_Throw() { await Assert.ThrowsAsync <ArgumentNullException>(() => TarFile.ExtractToDirectoryAsync(sourceFileName: null, destinationDirectoryName: "path", overwriteFiles: false)); await Assert.ThrowsAsync <ArgumentException>(() => TarFile.ExtractToDirectoryAsync(sourceFileName: string.Empty, destinationDirectoryName: "path", overwriteFiles: false)); await Assert.ThrowsAsync <ArgumentNullException>(() => TarFile.ExtractToDirectoryAsync(sourceFileName: "path", destinationDirectoryName: null, overwriteFiles: false)); await Assert.ThrowsAsync <ArgumentException>(() => TarFile.ExtractToDirectoryAsync(sourceFileName: "path", destinationDirectoryName: string.Empty, overwriteFiles: false)); }
public async Task UnreadableStream_Throws_Async() { using (MemoryStream archive = new MemoryStream()) { using (WrappedStream unreadable = new WrappedStream(archive, canRead: false, canWrite: true, canSeek: true)) { await Assert.ThrowsAsync <IOException>(() => TarFile.ExtractToDirectoryAsync(unreadable, destinationDirectoryName: "path", overwriteFiles: false)); } } }
public async Task UnwritableStream_Throws_Async() { await using (MemoryStream archiveStream = new MemoryStream()) { await using (WrappedStream unwritable = new WrappedStream(archiveStream, canRead: true, canWrite: false, canSeek: true)) { await Assert.ThrowsAsync <IOException>(() => TarFile.CreateFromDirectoryAsync(sourceDirectoryName: "path", destination: unwritable, includeBaseDirectory: false)); } } }
public async Task ExtractToDirectoryAsync_Cancel() { CancellationTokenSource cs = new CancellationTokenSource(); cs.Cancel(); using (MemoryStream archiveStream = new MemoryStream()) { await Assert.ThrowsAsync <TaskCanceledException>(() => TarFile.ExtractToDirectoryAsync(archiveStream, "directory", overwriteFiles: true, cs.Token)); } }
public DiskStream(TarFile archive, long length, string dir) { _archive = archive; _length = length; _dir = dir; if (!archive.DirExists(_dir)) { throw new IOException("No such disk"); } ReadChunkSkipList(); }