示例#1
0
        public void CanCreateATarFileWithMultipleFileEntriesWithADeepHierarchy()
        {
            using (Stream outStream = BuildOutStream())
            {
                using (var writer = new TarWriter(outStream))
                using (var entry1 = GetFileEntryFrom(@"deep\1.txt"))
                using (var entry2 = GetFileEntryFrom(@"deep\2\fox.txt"))
                using (var entry3 = GetFileEntryFrom(@"deep\2\3\dog.txt"))
                {
                    writer.Write(entry1.Path, entry1.Stream, 511, new DateTime(2013, 4, 1, 13, 12, 58, 548).ToUniversalTime());
                    writer.Write(entry2.Path, entry2.Stream, 511, new DateTime(2013, 4, 1, 13, 12, 58, 548).ToUniversalTime());
                    writer.Write(entry3.Path, entry3.Stream, 511, new DateTime(2013, 4, 1, 13, 12, 58, 548).ToUniversalTime());
                }

                outStream.Seek(0, SeekOrigin.Begin);

                using (var reader = new StreamReader(outStream))
                using (var expectedContentStream = GetExpectedStream("CanCreateATarFileWithMultipleFileEntriesWithADeepHierarchy"))
                {
                    string content = reader.ReadToEnd();
                    string expectedContent = expectedContentStream.ReadToEnd();

                    Assert.Equal(expectedContent, content);
                }
            }
        }
示例#2
0
        public static Stream CreateTarStream(IList<string> paths, CancellationToken cancellationToken, IProgress<string> progress = null)
        {
            var pipe = new Pipe();
            var reader = new PipeReadStream(pipe);
            try
            {
                var tarTask = Task.Run(async () =>
                {
                    using (var writer = new PipeWriteStream(pipe))
                    {
                        try
                        {
                            var tar = new TarWriter(writer);
                            foreach (var path in paths)
                            {
                                var fi = new FileInfo(path);
                                if (fi.Attributes.HasFlag(FileAttributes.Directory))
                                {
                                    await tar.CreateEntriesFromDirectoryAsync(path, ".", cancellationToken, progress);
                                }
                                else
                                {
                                    if (progress != null)
                                    {
                                        progress.Report(path);
                                    }

                                    await tar.CreateEntryFromFileAsync(path, Path.GetFileName(path), cancellationToken);
                                }
                            }
                            await tar.CloseAsync();
                        }
                        catch (Exception e)
                        {
                            writer.Close(e);
                            throw;
                        }

                        writer.Close();
                    }
                }, cancellationToken);
            }
            catch (Exception e)
            {
                reader.Close(e);
                throw;
            }

            return reader;
        }
示例#3
0
        public async Task WriteFifo_Async()
        {
            await using (MemoryStream archiveStream = new MemoryStream())
            {
                await using (TarWriter writer = new TarWriter(archiveStream, TarEntryFormat.Pax, leaveOpen: true))
                {
                    PaxTarEntry fifo = new PaxTarEntry(TarEntryType.Fifo, InitialEntryName);
                    SetFifo(fifo);
                    VerifyFifo(fifo);
                    await writer.WriteEntryAsync(fifo);
                }

                archiveStream.Position = 0;
                await using (TarReader reader = new TarReader(archiveStream))
                {
                    PaxTarEntry fifo = await reader.GetNextEntryAsync() as PaxTarEntry;

                    VerifyFifo(fifo);
                }
            }
        }
示例#4
0
        public async Task WriteBlockDevice_Async()
        {
            await using (MemoryStream archiveStream = new MemoryStream())
            {
                await using (TarWriter writer = new TarWriter(archiveStream, TarEntryFormat.Pax, leaveOpen: true))
                {
                    PaxTarEntry blockDevice = new PaxTarEntry(TarEntryType.BlockDevice, InitialEntryName);
                    SetBlockDevice(blockDevice);
                    VerifyBlockDevice(blockDevice);
                    await writer.WriteEntryAsync(blockDevice);
                }

                archiveStream.Position = 0;
                await using (TarReader reader = new TarReader(archiveStream))
                {
                    PaxTarEntry blockDevice = await reader.GetNextEntryAsync() as PaxTarEntry;

                    VerifyBlockDevice(blockDevice);
                }
            }
        }
示例#5
0
 private void InitializeArchive()
 {
     if (archiveFileName1 == null)
     {
         archiveFileName1 = Path.GetTempFileName();
         SharedData.Instance.ArchiveFileName = archiveFileName1;
         SharedData.Instance.TempFiles.Add(archiveFileName1);
     }
     //gzFile = File.Create(archiveFileName1);
     //gzFile.SetLength(0);
     //SharedData.Instance.OpenDisposables.Add(gzFile);
     //gzStream = new GZipStream(gzFile, CompressionMode.Compress, false);
     //SharedData.Instance.OpenDisposables.Add(gzStream);
     //tarWriter = new TarWriter(gzStream);
     tarFile = File.Create(archiveFileName1);
     tarFile.SetLength(0);
     SharedData.Instance.OpenDisposables.Add(tarFile);
     tarWriter = new TarWriter(tarFile);
     SharedData.Instance.OpenDisposables.Add(tarWriter);
     createdDirs.Clear();
 }
示例#6
0
        public async Task WriteRegularFile_Async()
        {
            await using (MemoryStream archiveStream = new MemoryStream())
            {
                await using (TarWriter writer = new TarWriter(archiveStream, TarEntryFormat.Pax, leaveOpen: true))
                {
                    PaxTarEntry regularFile = new PaxTarEntry(TarEntryType.RegularFile, InitialEntryName);
                    SetRegularFile(regularFile);
                    VerifyRegularFile(regularFile, isWritable: true);
                    await writer.WriteEntryAsync(regularFile);
                }

                archiveStream.Position = 0;
                await using (TarReader reader = new TarReader(archiveStream))
                {
                    PaxTarEntry regularFile = await reader.GetNextEntryAsync() as PaxTarEntry;

                    VerifyRegularFile(regularFile, isWritable: false);
                }
            }
        }
示例#7
0
 public override void Import(Stream input, Stream output, string filename)
 {
     using (var importer = new AssimpContext()) {
         var scene = importer.ImportFileFromStream(input,
                                                   PostProcessSteps.Triangulate | PostProcessSteps.SortByPrimitiveType | PostProcessSteps.GenerateNormals,
                                                   Path.GetExtension(filename));
         using (var tw = new TarWriter(output)) {
             var textures = new Dictionary <string, string>();
             using (var ms = new MemoryStream()) {
                 using (var bw = new BinaryWriter(ms)) {
                     this.WriteModel(scene, bw, textures);
                     bw.Flush();
                     //this.PrintNode(scene, scene.RootNode, 0);
                     ms.Position = 0;
                     tw.Write(ms, ms.Length, "model.bin");
                 }
             }
             this.WriteTextures(scene, tw, textures);
         }
     }
 }
示例#8
0
        public void Write_V7RegularFileEntry_As_RegularFileEntry()
        {
            using MemoryStream archive = new MemoryStream();
            using (TarWriter writer = new TarWriter(archive, archiveFormat: TarFormat.Pax, leaveOpen: true))
            {
                V7TarEntry entry = new V7TarEntry(TarEntryType.V7RegularFile, InitialEntryName);

                // Should be written as RegularFile
                writer.WriteEntry(entry);
            }

            archive.Seek(0, SeekOrigin.Begin);
            using (TarReader reader = new TarReader(archive))
            {
                PaxTarEntry entry = reader.GetNextEntry() as PaxTarEntry;
                Assert.NotNull(entry);
                Assert.Equal(TarEntryType.RegularFile, entry.EntryType);

                Assert.Null(reader.GetNextEntry());
            }
        }
示例#9
0
        public void Write_To_UnseekableStream()
        {
            using MemoryStream inner    = new MemoryStream();
            using WrappedStream wrapped = new WrappedStream(inner, canRead: true, canWrite: true, canSeek: false);

            using (TarWriter writer = new TarWriter(wrapped, leaveOpen: true))
            {
                PaxTarEntry paxEntry = new PaxTarEntry(TarEntryType.RegularFile, "file.txt");
                writer.WriteEntry(paxEntry);
            } // The final records should get written, and the length should not be set because position cannot be read

            inner.Seek(0, SeekOrigin.Begin); // Rewind the base stream (wrapped cannot be rewound)

            using (TarReader reader = new TarReader(wrapped))
            {
                TarEntry entry = reader.GetNextEntry();
                Assert.Equal(TarFormat.Pax, reader.Format);
                Assert.Equal(TarEntryType.RegularFile, entry.EntryType);
                Assert.Null(reader.GetNextEntry());
            }
        }
示例#10
0
        public async Task Extract_LinkEntry_TargetOutsideDirectory_Async(TarEntryType entryType)
        {
            await using (MemoryStream archive = new MemoryStream())
            {
                await using (TarWriter writer = new TarWriter(archive, TarEntryFormat.Ustar, leaveOpen: true))
                {
                    UstarTarEntry entry = new UstarTarEntry(entryType, "link");
                    entry.LinkName = PlatformDetection.IsWindows ? @"C:\Windows\System32\notepad.exe" : "/usr/bin/nano";
                    await writer.WriteEntryAsync(entry);
                }

                archive.Seek(0, SeekOrigin.Begin);

                using (TempDirectory root = new TempDirectory())
                {
                    await Assert.ThrowsAsync <IOException>(() => TarFile.ExtractToDirectoryAsync(archive, root.Path, overwriteFiles: false));

                    Assert.Equal(0, Directory.GetFileSystemEntries(root.Path).Count());
                }
            }
        }
示例#11
0
        public async Task WriteSymbolicLink_Async()
        {
            await using (MemoryStream archiveStream = new MemoryStream())
            {
                await using (TarWriter writer = new TarWriter(archiveStream, TarEntryFormat.Pax, leaveOpen: true))
                {
                    PaxTarEntry symbolicLink = new PaxTarEntry(TarEntryType.SymbolicLink, InitialEntryName);
                    SetSymbolicLink(symbolicLink);
                    VerifySymbolicLink(symbolicLink);
                    await writer.WriteEntryAsync(symbolicLink);
                }

                archiveStream.Position = 0;
                await using (TarReader reader = new TarReader(archiveStream))
                {
                    PaxTarEntry symbolicLink = await reader.GetNextEntryAsync() as PaxTarEntry;

                    VerifySymbolicLink(symbolicLink);
                }
            }
        }
示例#12
0
        private async Task Verify_Checksum_Internal_Async(TarEntryFormat format, TarEntryType entryType, bool longPath, bool longLink)
        {
            using MemoryStream archive = new MemoryStream();
            int expectedChecksum;

            await using (TarWriter writer = new TarWriter(archive, format, leaveOpen: true))
            {
                TarEntry entry = CreateTarEntryAndGetExpectedChecksum(format, entryType, longPath, longLink, out expectedChecksum);
                await writer.WriteEntryAsync(entry);

                Assert.Equal(expectedChecksum, entry.Checksum);
            }

            archive.Seek(0, SeekOrigin.Begin);
            await using (TarReader reader = new TarReader(archive))
            {
                TarEntry entry = await reader.GetNextEntryAsync();

                Assert.Equal(expectedChecksum, entry.Checksum);
            }
        }
示例#13
0
        public async Task WriteDirectory_Async()
        {
            await using (MemoryStream archiveStream = new MemoryStream())
            {
                await using (TarWriter writer = new TarWriter(archiveStream, TarEntryFormat.Pax, leaveOpen: true))
                {
                    PaxTarEntry directory = new PaxTarEntry(TarEntryType.Directory, InitialEntryName);
                    SetDirectory(directory);
                    VerifyDirectory(directory);
                    await writer.WriteEntryAsync(directory);
                }

                archiveStream.Position = 0;
                await using (TarReader reader = new TarReader(archiveStream))
                {
                    PaxTarEntry directory = await reader.GetNextEntryAsync() as PaxTarEntry;

                    VerifyDirectory(directory);
                }
            }
        }
示例#14
0
        /// <summary>
        /// Adds every file in the directory to the tar, and recurses into subdirectories.
        /// </summary>
        private void AddAllToTar(string root, TarWriter tar)
        {
            Log("Opening in " + root + "...");

            // Add subdirectories...
            foreach (var directory in Directory.GetDirectories(root))
            {
                AddAllToTar(directory, tar);
            }

            foreach (var file in Directory.GetFiles(root))
            {
                var info = new FileInfo(file);
                Log("Writing " + info.Name + "... (" + Util.FormatFileSize(info.Length) + ")");

                using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    tar.Write(fs);
                }
            }
        }
示例#15
0
        public async Task EntryName_NullOrEmpty_Async()
        {
            using (TempDirectory root = new TempDirectory())
            {
                string file1Name = "file1.txt";
                string file2Name = "file2.txt";

                string file1Path = Path.Join(root.Path, file1Name);
                string file2Path = Path.Join(root.Path, file2Name);

                File.Create(file1Path).Dispose();
                File.Create(file2Path).Dispose();

                await using (MemoryStream archiveStream = new MemoryStream())
                {
                    await using (TarWriter writer = new TarWriter(archiveStream, TarEntryFormat.Pax, leaveOpen: true))
                    {
                        await writer.WriteEntryAsync(file1Path, null);

                        await writer.WriteEntryAsync(file2Path, string.Empty);
                    }

                    archiveStream.Seek(0, SeekOrigin.Begin);
                    await using (TarReader reader = new TarReader(archiveStream))
                    {
                        TarEntry first = await reader.GetNextEntryAsync();

                        Assert.NotNull(first);
                        Assert.Equal(file1Name, first.Name);

                        TarEntry second = await reader.GetNextEntryAsync();

                        Assert.NotNull(second);
                        Assert.Equal(file2Name, second.Name);

                        Assert.Null(await reader.GetNextEntryAsync());
                    }
                }
            }
        }
示例#16
0
        public async Task WritePaxAttributes_LongLinkName_AutomaticallyAdded_Async()
        {
            using MemoryStream archiveStream = new MemoryStream();

            string longSymbolicLinkName = new string('a', 101);
            string longHardLinkName     = new string('b', 101);

            await using (TarWriter writer = new TarWriter(archiveStream, TarEntryFormat.Pax, leaveOpen: true))
            {
                PaxTarEntry symlink = new PaxTarEntry(TarEntryType.SymbolicLink, "symlink");
                symlink.LinkName = longSymbolicLinkName;
                await writer.WriteEntryAsync(symlink);

                PaxTarEntry hardlink = new PaxTarEntry(TarEntryType.HardLink, "hardlink");
                hardlink.LinkName = longHardLinkName;
                await writer.WriteEntryAsync(hardlink);
            }

            archiveStream.Position = 0;
            await using (TarReader reader = new TarReader(archiveStream))
            {
                PaxTarEntry symlink = await reader.GetNextEntryAsync() as PaxTarEntry;

                AssertExtensions.GreaterThanOrEqualTo(symlink.ExtendedAttributes.Count, 5);

                Assert.Contains(PaxEaName, symlink.ExtendedAttributes);
                Assert.Equal("symlink", symlink.ExtendedAttributes[PaxEaName]);
                Assert.Contains(PaxEaLinkName, symlink.ExtendedAttributes);
                Assert.Equal(longSymbolicLinkName, symlink.ExtendedAttributes[PaxEaLinkName]);

                PaxTarEntry hardlink = await reader.GetNextEntryAsync() as PaxTarEntry;

                AssertExtensions.GreaterThanOrEqualTo(hardlink.ExtendedAttributes.Count, 5);

                Assert.Contains(PaxEaName, hardlink.ExtendedAttributes);
                Assert.Equal("hardlink", hardlink.ExtendedAttributes[PaxEaName]);
                Assert.Contains(PaxEaLinkName, hardlink.ExtendedAttributes);
                Assert.Equal(longHardLinkName, hardlink.ExtendedAttributes[PaxEaLinkName]);
            }
        }
        public void Add_SymbolicLink(TarEntryFormat format, bool createTarget)
        {
            using TempDirectory root = new TempDirectory();
            string targetName = "file.txt";
            string linkName   = "link.txt";
            string targetPath = Path.Join(root.Path, targetName);
            string linkPath   = Path.Join(root.Path, linkName);

            if (createTarget)
            {
                File.Create(targetPath).Dispose();
            }

            FileInfo linkInfo = new FileInfo(linkPath);

            linkInfo.CreateAsSymbolicLink(targetName);

            using MemoryStream archive = new MemoryStream();
            using (TarWriter writer = new TarWriter(archive, format, leaveOpen: true))
            {
                writer.WriteEntry(fileName: linkPath, entryName: linkName);
            }

            archive.Seek(0, SeekOrigin.Begin);
            using (TarReader reader = new TarReader(archive))
            {
                TarEntry entry = reader.GetNextEntry();
                Assert.Equal(format, entry.Format);

                Assert.NotNull(entry);
                Assert.Equal(linkName, entry.Name);
                Assert.Equal(targetName, entry.LinkName);
                Assert.Equal(TarEntryType.SymbolicLink, entry.EntryType);
                Assert.Null(entry.DataStream);

                VerifyPlatformSpecificMetadata(linkPath, entry);

                Assert.Null(reader.GetNextEntry());
            }
        }
        public void Add_CharacterDevice(TarEntryFormat format)
        {
            RemoteExecutor.Invoke((string strFormat) =>
            {
                TarEntryFormat expectedFormat = Enum.Parse <TarEntryFormat>(strFormat);
                using TempDirectory root      = new TempDirectory();
                string characterDevicePath    = Path.Join(root.Path, AssetCharacterDeviceFileName);

                // Creating device files needs elevation
                Interop.CheckIo(Interop.Sys.CreateCharacterDevice(characterDevicePath, (int)DefaultFileMode, TestCharacterDeviceMajor, TestCharacterDeviceMinor));

                using MemoryStream archive = new MemoryStream();
                using (TarWriter writer = new TarWriter(archive, expectedFormat, leaveOpen: true))
                {
                    writer.WriteEntry(fileName: characterDevicePath, entryName: AssetCharacterDeviceFileName);
                }

                archive.Seek(0, SeekOrigin.Begin);
                using (TarReader reader = new TarReader(archive))
                {
                    PosixTarEntry entry = reader.GetNextEntry() as PosixTarEntry;
                    Assert.Equal(expectedFormat, entry.Format);

                    Assert.NotNull(entry);
                    Assert.Equal(AssetCharacterDeviceFileName, entry.Name);
                    Assert.Equal(DefaultLinkName, entry.LinkName);
                    Assert.Equal(TarEntryType.CharacterDevice, entry.EntryType);
                    Assert.Null(entry.DataStream);

                    VerifyPlatformSpecificMetadata(characterDevicePath, entry);

                    Assert.Equal(TestCharacterDeviceMajor, entry.DeviceMajor);
                    Assert.Equal(TestCharacterDeviceMinor, entry.DeviceMinor);

                    Assert.Null(reader.GetNextEntry());
                }
            }, format.ToString(), new RemoteInvokeOptions {
                RunAsSudo = true
            }).Dispose();
        }
示例#19
0
        public async Task WritePaxAttributes_Name_AutomaticallyAdded_Async()
        {
            using MemoryStream archiveStream = new MemoryStream();
            TarWriter writer = new TarWriter(archiveStream, TarEntryFormat.Pax, leaveOpen: true);

            await using (writer)
            {
                PaxTarEntry regularFile = new PaxTarEntry(TarEntryType.RegularFile, InitialEntryName);
                await writer.WriteEntryAsync(regularFile);
            }

            archiveStream.Position = 0;
            TarReader reader = new TarReader(archiveStream);

            await using (reader)
            {
                PaxTarEntry regularFile = await reader.GetNextEntryAsync() as PaxTarEntry;

                AssertExtensions.GreaterThanOrEqualTo(regularFile.ExtendedAttributes.Count, 4);
                Assert.Contains(PaxEaName, regularFile.ExtendedAttributes);
            }
        }
示例#20
0
        public async Task WriteTimestampsBeyondEpochalypse_Async(TarEntryFormat format)
        {
            DateTimeOffset epochalypse = new DateTimeOffset(2038, 1, 19, 3, 14, 8, TimeSpan.Zero); // One second past Y2K38
            TarEntry       entry       = InvokeTarEntryCreationConstructor(format, TarEntryType.Directory, "dir");

            entry.ModificationTime = epochalypse;
            Assert.Equal(epochalypse, entry.ModificationTime);

            if (entry is GnuTarEntry gnuEntry)
            {
                gnuEntry.AccessTime = epochalypse;
                Assert.Equal(epochalypse, gnuEntry.AccessTime);

                gnuEntry.ChangeTime = epochalypse;
                Assert.Equal(epochalypse, gnuEntry.ChangeTime);
            }

            using MemoryStream archiveStream = new MemoryStream();
            await using (TarWriter writer = new TarWriter(archiveStream, leaveOpen: true))
            {
                await writer.WriteEntryAsync(entry);
            }

            archiveStream.Position = 0;
            await using (TarReader reader = new TarReader(archiveStream))
            {
                TarEntry readEntry = await reader.GetNextEntryAsync();

                Assert.NotNull(readEntry);

                Assert.Equal(epochalypse, readEntry.ModificationTime);

                if (readEntry is GnuTarEntry gnuReadEntry)
                {
                    Assert.Equal(epochalypse, gnuReadEntry.AccessTime);
                    Assert.Equal(epochalypse, gnuReadEntry.ChangeTime);
                }
            }
        }
示例#21
0
        public async Task ReadAndWriteMultipleGlobalExtendedAttributesEntries_Async(TarEntryFormat format)
        {
            Dictionary <string, string> attrs = new Dictionary <string, string>()
            {
                { "hello", "world" },
                { "dotnet", "runtime" }
            };

            using MemoryStream archiveStream = new MemoryStream();
            TarWriter writer = new TarWriter(archiveStream, leaveOpen: true);

            await using (writer)
            {
                PaxGlobalExtendedAttributesTarEntry gea1 = new PaxGlobalExtendedAttributesTarEntry(attrs);
                await writer.WriteEntryAsync(gea1);

                TarEntry entry1 = InvokeTarEntryCreationConstructor(format, TarEntryType.Directory, "dir1");
                await writer.WriteEntryAsync(entry1);

                PaxGlobalExtendedAttributesTarEntry gea2 = new PaxGlobalExtendedAttributesTarEntry(attrs);
                await writer.WriteEntryAsync(gea2);

                TarEntry entry2 = InvokeTarEntryCreationConstructor(format, TarEntryType.Directory, "dir2");
                await writer.WriteEntryAsync(entry2);
            }

            archiveStream.Position = 0;

            TarReader reader = new TarReader(archiveStream, leaveOpen: false);

            await using (reader)
            {
                VerifyGlobalExtendedAttributesEntry(await reader.GetNextEntryAsync(), attrs);
                VerifyDirectory(await reader.GetNextEntryAsync(), format, "dir1");
                VerifyGlobalExtendedAttributesEntry(await reader.GetNextEntryAsync(), attrs);
                VerifyDirectory(await reader.GetNextEntryAsync(), format, "dir2");
                Assert.Null(await reader.GetNextEntryAsync());
            }
        }
        public void Add_Fifo(TarEntryFormat format)
        {
            RemoteExecutor.Invoke((string strFormat) =>
            {
                TarEntryFormat expectedFormat = Enum.Parse <TarEntryFormat>(strFormat);

                using TempDirectory root = new TempDirectory();
                string fifoName          = "fifofile";
                string fifoPath          = Path.Join(root.Path, fifoName);

                Interop.CheckIo(Interop.Sys.MkFifo(fifoPath, (int)DefaultMode));

                using MemoryStream archive = new MemoryStream();
                using (TarWriter writer = new TarWriter(archive, expectedFormat, leaveOpen: true))
                {
                    writer.WriteEntry(fileName: fifoPath, entryName: fifoName);
                }

                archive.Seek(0, SeekOrigin.Begin);
                using (TarReader reader = new TarReader(archive))
                {
                    Assert.Equal(TarEntryFormat.Unknown, reader.Format);
                    PosixTarEntry entry = reader.GetNextEntry() as PosixTarEntry;
                    Assert.Equal(expectedFormat, reader.Format);

                    Assert.NotNull(entry);
                    Assert.Equal(fifoName, entry.Name);
                    Assert.Equal(DefaultLinkName, entry.LinkName);
                    Assert.Equal(TarEntryType.Fifo, entry.EntryType);
                    Assert.Null(entry.DataStream);

                    VerifyPlatformSpecificMetadata(fifoPath, entry);

                    Assert.Null(reader.GetNextEntry());
                }
            }, format.ToString(), new RemoteInvokeOptions {
                RunAsSudo = true
            }).Dispose();
        }
        public async Task BlockAlignmentPadding_DoesNotAffectNextEntries_Async(int contentSize, bool copyData)
        {
            byte[] fileContents = new byte[contentSize];
            Array.Fill <byte>(fileContents, 0x1);

            using var archive = new MemoryStream();
            using (var writer = new TarWriter(archive, leaveOpen: true))
            {
                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 unseekable = new WrappedStream(archive, archive.CanRead, archive.CanWrite, canSeek: false);
            using var reader     = new TarReader(unseekable);

            TarEntry e = await reader.GetNextEntryAsync(copyData);

            Assert.Equal(contentSize, e.Length);

            byte[] buffer = new byte[contentSize];
            while (e.DataStream.Read(buffer) > 0)
            {
                ;
            }
            AssertExtensions.SequenceEqual(fileContents, buffer);

            e = await reader.GetNextEntryAsync(copyData);

            Assert.Equal(0, e.Length);

            e = await reader.GetNextEntryAsync(copyData);

            Assert.Null(e);
        }
示例#24
0
        public void WritePaxAttributes_Timestamps_AutomaticallyAdded()
        {
            DateTimeOffset minimumTime = DateTimeOffset.UtcNow - TimeSpan.FromHours(1);

            using MemoryStream archiveStream = new MemoryStream();
            using (TarWriter writer = new TarWriter(archiveStream, TarEntryFormat.Pax, leaveOpen: true))
            {
                PaxTarEntry regularFile = new PaxTarEntry(TarEntryType.RegularFile, InitialEntryName);
                writer.WriteEntry(regularFile);
            }

            archiveStream.Position = 0;
            using (TarReader reader = new TarReader(archiveStream))
            {
                PaxTarEntry regularFile = reader.GetNextEntry() as PaxTarEntry;

                AssertExtensions.GreaterThanOrEqualTo(regularFile.ExtendedAttributes.Count, 4);
                VerifyExtendedAttributeTimestamp(regularFile, PaxEaMTime, minimumTime);
                VerifyExtendedAttributeTimestamp(regularFile, PaxEaATime, minimumTime);
                VerifyExtendedAttributeTimestamp(regularFile, PaxEaCTime, minimumTime);
            }
        }
示例#25
0
        public void Write_V7RegularFileEntry_In_OtherFormatsWriter(TarEntryFormat writerFormat)
        {
            using MemoryStream archive = new MemoryStream();
            using (TarWriter writer = new TarWriter(archive, format: writerFormat, leaveOpen: true))
            {
                V7TarEntry entry = new V7TarEntry(TarEntryType.V7RegularFile, InitialEntryName);

                // Should be written in the format of the entry
                writer.WriteEntry(entry);
            }

            archive.Seek(0, SeekOrigin.Begin);
            using (TarReader reader = new TarReader(archive))
            {
                TarEntry entry = reader.GetNextEntry();
                Assert.NotNull(entry);
                Assert.Equal(TarEntryFormat.V7, entry.Format);
                Assert.True(entry is V7TarEntry);

                Assert.Null(reader.GetNextEntry());
            }
        }
示例#26
0
        public void UnixFileModes_RestrictiveParentDir(bool overwrite)
        {
            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);
            }

            string dirPath  = Path.Join(destination.Path, "dir");
            string filePath = Path.Join(dirPath, "file");

            if (overwrite)
            {
                Directory.CreateDirectory(dirPath);
                File.OpenWrite(filePath).Dispose();
            }

            TarFile.ExtractToDirectory(archivePath, destination.Path, overwriteFiles: overwrite);

            Assert.True(Directory.Exists(dirPath), $"{dirPath}' does not exist.");
            AssertFileModeEquals(dirPath, UnixFileMode.None);

            // Set dir permissions so we can access file.
            SetUnixFileMode(dirPath, UserAll);

            Assert.True(File.Exists(filePath), $"{filePath}' does not exist.");
            AssertFileModeEquals(filePath, TestPermission1);
        }
示例#27
0
        public void Write_LongLinkName(TarEntryType entryType)
        {
            // LinkName field in header only fits 100 bytes
            string longLinkName = new string('a', 101);

            using MemoryStream archiveStream = new MemoryStream();
            using (TarWriter writer = new TarWriter(archiveStream, TarEntryFormat.Gnu, leaveOpen: true))
            {
                GnuTarEntry entry = new GnuTarEntry(entryType, "file.txt");
                entry.LinkName = longLinkName;
                writer.WriteEntry(entry);
            }

            archiveStream.Position = 0;
            using (TarReader reader = new TarReader(archiveStream))
            {
                GnuTarEntry entry = reader.GetNextEntry() as GnuTarEntry;
                Assert.Equal(entryType, entry.EntryType);
                Assert.Equal("file.txt", entry.Name);
                Assert.Equal(longLinkName, entry.LinkName);
            }
        }
        public void Add_Directory(TarEntryFormat format, bool withContents)
        {
            using TempDirectory root = new TempDirectory();
            string dirName = "dir";
            string dirPath = Path.Join(root.Path, dirName);

            Directory.CreateDirectory(dirPath);

            if (withContents)
            {
                // Add a file inside the directory, we need to ensure the contents
                // of the directory are ignored when using AddFile
                File.Create(Path.Join(dirPath, "file.txt")).Dispose();
            }

            using MemoryStream archive = new MemoryStream();
            using (TarWriter writer = new TarWriter(archive, format, leaveOpen: true))
            {
                writer.WriteEntry(fileName: dirPath, entryName: dirName);
            }

            archive.Seek(0, SeekOrigin.Begin);
            using (TarReader reader = new TarReader(archive))
            {
                Assert.Equal(TarEntryFormat.Unknown, reader.Format);
                TarEntry entry = reader.GetNextEntry();
                Assert.Equal(format, reader.Format);

                Assert.NotNull(entry);
                Assert.Equal(dirName, entry.Name);
                Assert.Equal(TarEntryType.Directory, entry.EntryType);
                Assert.Null(entry.DataStream);

                VerifyPlatformSpecificMetadata(dirPath, entry);

                Assert.Null(reader.GetNextEntry()); // If the dir had contents, they should've been excluded
            }
        }
        public void TarReaderWriter()
        {
            var checks = new Dictionary <string, byte[]>();
            var random = new Random();

            byte[] data;
            using (var stream = new MemoryStream())
            {
                using (var writer = new TarWriter(stream, true))
                {
                    for (var i = 0; i < 1000; i++)
                    {
                        var buffer = new byte[random.Next(64 * 1024)];
                        var name   = $"{i % 10}/{i} {buffer.GetHashCode().ToString("x")}.txt";
                        checks.Add(name, buffer);
                        writer.AddFile(name, buffer);
                    }
                }
                data = stream.ToArray();
            }
            using (var stream = new MemoryStream(data))
            {
                using (var reader = new TarReader(stream, true))
                {
                    var copy = checks.ToDictionary(i => i.Key, i => i.Value);
                    while (reader.ReadNext(out var entry, out var content))
                    {
                        if (!copy.TryGetValue(entry.Name, out var expectedContent))
                        {
                            Assert.Fail("Entry name not found at source!");
                        }

                        copy.Remove(entry.Name);
                        CollectionAssert.AreEqual(expectedContent, content);
                    }
                }
            }
        }
示例#30
0
        public void WritePaxAttributes_CustomAttribute()
        {
            string expectedKey   = "MyExtendedAttributeKey";
            string expectedValue = "MyExtendedAttributeValue";

            Dictionary <string, string> extendedAttributes = new();

            extendedAttributes.Add(expectedKey, expectedValue);

            using MemoryStream archiveStream = new MemoryStream();
            using (TarWriter writer = new TarWriter(archiveStream, TarEntryFormat.Pax, leaveOpen: true))
            {
                PaxTarEntry regularFile = new PaxTarEntry(TarEntryType.RegularFile, InitialEntryName, extendedAttributes);
                SetRegularFile(regularFile);
                VerifyRegularFile(regularFile, isWritable: true);
                writer.WriteEntry(regularFile);
            }

            archiveStream.Position = 0;
            using (TarReader reader = new TarReader(archiveStream))
            {
                PaxTarEntry regularFile = reader.GetNextEntry() as PaxTarEntry;
                VerifyRegularFile(regularFile, isWritable: false);

                Assert.NotNull(regularFile.ExtendedAttributes);

                // path, mtime, atime and ctime are always collected by default
                Assert.True(regularFile.ExtendedAttributes.Count >= 5);

                Assert.Contains("path", regularFile.ExtendedAttributes);
                Assert.Contains("mtime", regularFile.ExtendedAttributes);
                Assert.Contains("atime", regularFile.ExtendedAttributes);
                Assert.Contains("ctime", regularFile.ExtendedAttributes);

                Assert.Contains(expectedKey, regularFile.ExtendedAttributes);
                Assert.Equal(expectedValue, regularFile.ExtendedAttributes[expectedKey]);
            }
        }
示例#31
0
        public async Task Write_Long_Name_Async(TarEntryType entryType)
        {
            // Name field in header only fits 100 bytes
            string longName = new string('a', 101);

            await using (MemoryStream archiveStream = new MemoryStream())
            {
                await using (TarWriter writer = new TarWriter(archiveStream, TarEntryFormat.Gnu, leaveOpen: true))
                {
                    GnuTarEntry entry = new GnuTarEntry(entryType, longName);
                    await writer.WriteEntryAsync(entry);
                }

                archiveStream.Position = 0;
                await using (TarReader reader = new TarReader(archiveStream))
                {
                    GnuTarEntry entry = await reader.GetNextEntryAsync() as GnuTarEntry;

                    Assert.Equal(entryType, entry.EntryType);
                    Assert.Equal(longName, entry.Name);
                }
            }
        }
        public void LongEndMarkers_DoNotAdvanceStream()
        {
            using MemoryStream archive = new MemoryStream();

            using (TarWriter writer = new TarWriter(archive, TarEntryFormat.Ustar, leaveOpen: true))
            {
                UstarTarEntry entry = new UstarTarEntry(TarEntryType.Directory, "dir");
                writer.WriteEntry(entry);
            }

            byte[] buffer = new byte[2048]; // Four additional end markers (512 each)
            Array.Fill <byte>(buffer, 0x0);
            archive.Write(buffer);
            archive.Seek(0, SeekOrigin.Begin);

            using TarReader reader = new TarReader(archive);
            Assert.NotNull(reader.GetNextEntry());
            Assert.Null(reader.GetNextEntry());
            long expectedPosition = archive.Position; // After reading the first null entry, should not advance more

            Assert.Null(reader.GetNextEntry());
            Assert.Equal(expectedPosition, archive.Position);
        }
示例#33
0
        public void CanCreateATarFileWithOneFileEntry()
        {
            using (Stream outStream = BuildOutStream())
            {
                using (var writer = new TarWriter(outStream))
                using (var entry = GetFileEntryFrom(@"single\1.txt"))
                {
                    writer.Write(entry.Path, entry.Stream, 511, new DateTime(2013, 4, 1, 13, 12, 58, 548).ToUniversalTime());
                }

                outStream.Seek(0, SeekOrigin.Begin);

                using (var reader = new StreamReader(outStream))
                using (var expectedContentStream = GetExpectedStream("CanCreateATarFileWithOneFileEntry"))
                {
                    string content = reader.ReadToEnd();
                    string expectedContent = expectedContentStream.ReadToEnd();

                    Assert.Equal(expectedContent, content);
                }
            }
        }
示例#34
0
 public TarWriterStream(TarWriter writer)
 {
     _writer = writer;
 }