Example #1
0
 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));
 }
Example #2
0
        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
            }
        }
        // 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 void Extract_LinkEntry_TargetInsideDirectory_Internal(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();

            using MemoryStream archive = new MemoryStream();
            using (TarWriter writer = new TarWriter(archive, format, leaveOpen: true))
            {
                TarEntry entry = InvokeTarEntryCreationConstructor(format, entryType, linkName);
                entry.LinkName = targetPath;
                writer.WriteEntry(entry);
            }

            archive.Seek(0, SeekOrigin.Begin);

            TarFile.ExtractToDirectory(archive, baseDir, overwriteFiles: false);

            Assert.Equal(2, Directory.GetFileSystemEntries(baseDir).Count());
        }
Example #4
0
        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
        }
Example #5
0
        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)));
        }
Example #6
0
        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.");
        }
Example #7
0
        public void Extract_UnseekableStream_BlockAlignmentPadding_DoesNotAffectNextEntries(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);
                writer.WriteEntry(entry1);

                var entry2 = new PaxTarEntry(TarEntryType.RegularFile, "next-file");
                writer.WriteEntry(entry2);
            }

            archive.Position       = 0;
            using var decompressor = new GZipStream(archive, CompressionMode.Decompress);
            using var reader       = new TarReader(decompressor);

            using TempDirectory destination = new TempDirectory();
            TarFile.ExtractToDirectory(decompressor, destination.Path, overwriteFiles: true);

            Assert.Equal(2, Directory.GetFileSystemEntries(destination.Path, "*", SearchOption.AllDirectories).Count());
        }
Example #8
0
        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));
        }
Example #9
0
        public void NonExistentDirectory_Throws()
        {
            using TempDirectory root = new TempDirectory();

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

            File.Create(filePath).Dispose();

            Assert.Throws <DirectoryNotFoundException>(() => TarFile.ExtractToDirectory(sourceFileName: filePath, destinationDirectoryName: dirPath, overwriteFiles: false));
        }
Example #10
0
        public void Extract_Archive_File_OverwriteFalse()
        {
            string sourceArchiveFileName = GetTarFilePath(CompressionMethod.Uncompressed, TestTarFormat.pax, "file");

            using TempDirectory destination = new TempDirectory();

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

            File.Create(filePath).Dispose();

            Assert.Throws <IOException>(() => TarFile.ExtractToDirectory(sourceArchiveFileName, destination.Path, overwriteFiles: false));
        }
Example #11
0
        public void Extract_Archive_File(TestTarFormat testFormat)
        {
            string sourceArchiveFileName = GetTarFilePath(CompressionMethod.Uncompressed, testFormat, "file");

            using TempDirectory destination = new TempDirectory();

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

            TarFile.ExtractToDirectory(sourceArchiveFileName, destination.Path, overwriteFiles: false);

            Assert.True(File.Exists(filePath));
        }
        public void Extract_Archive_File_OverwriteFalse()
        {
            string sourceArchiveFileName = GetTarFilePath(CompressionMethod.Uncompressed, TestTarFormat.pax, "file");

            using TempDirectory destination = new TempDirectory();

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

            using (StreamWriter writer = File.CreateText(filePath))
            {
                writer.WriteLine("My existence should cause an exception");
            }

            Assert.Throws <IOException>(() => TarFile.ExtractToDirectory(sourceArchiveFileName, destination.Path, overwriteFiles: false));
        }
Example #13
0
        public void Extract_SpecialFiles_Unix_Unelevated_ThrowsUnauthorizedAccess()
        {
            string originalFileName = GetTarFilePath(CompressionMethod.Uncompressed, TestTarFormat.ustar, "specialfiles");
            using TempDirectory root = new TempDirectory();

            string archive = Path.Join(root.Path, "input.tar");
            string destination = Path.Join(root.Path, "dir");

            // Copying the tar to reduce the chance of other tests failing due to being used by another process
            File.Copy(originalFileName, archive);

            Directory.CreateDirectory(destination);

            Assert.Throws<UnauthorizedAccessException>(() => TarFile.ExtractToDirectory(archive, destination, overwriteFiles: false));

            Assert.Equal(0, Directory.GetFileSystemEntries(destination).Count());
        }
Example #14
0
        public void Extract_LinkEntry_TargetOutsideDirectory(TarEntryType entryType)
        {
            using MemoryStream archive = new MemoryStream();
            using (TarWriter writer = new TarWriter(archive, TarFormat.Ustar, leaveOpen: true))
            {
                UstarTarEntry entry = new UstarTarEntry(entryType, "link");
                entry.LinkName = PlatformDetection.IsWindows ? @"C:\Windows\System32\notepad.exe" : "/usr/bin/nano";
                writer.WriteEntry(entry);
            }

            archive.Seek(0, SeekOrigin.Begin);

            using TempDirectory root = new TempDirectory();

            Assert.Throws <IOException>(() => TarFile.ExtractToDirectory(archive, root.Path, overwriteFiles: false));

            Assert.Equal(0, Directory.GetFileSystemEntries(root.Path).Count());
        }
Example #15
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);
        }
Example #16
0
        public void ExtractArchiveWithEntriesThatStartWithSlashDotPrefix()
        {
            using TempDirectory root = new TempDirectory();

            using MemoryStream archiveStream = GetStrangeTarMemoryStream("prefixDotSlashAndCurrentFolderEntry");

            TarFile.ExtractToDirectory(archiveStream, root.Path, overwriteFiles: true);

            archiveStream.Position = 0;

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

            TarEntry entry;

            while ((entry = reader.GetNextEntry()) != null)
            {
                // Normalize the path (remove redundant segments), remove trailing separators
                // this is so the first entry can be skipped if it's the same as the root directory
                string entryPath = Path.TrimEndingDirectorySeparator(Path.GetFullPath(Path.Join(root.Path, entry.Name)));
                Assert.True(Path.Exists(entryPath), $"Entry was not extracted: {entryPath}");
            }
        }
Example #17
0
        public void TarGz_TarFile_CreateFromDir_ExtractToDir()
        {
            using TempDirectory root = new TempDirectory();

            string archivePath = Path.Join(root.Path, "compressed.tar.gz");

            string sourceDirectory = Path.Join(root.Path, "source");

            Directory.CreateDirectory(sourceDirectory);

            string destinationDirectory = Path.Join(root.Path, "destination");

            Directory.CreateDirectory(destinationDirectory);

            string fileName = "file.txt";
            string filePath = Path.Join(sourceDirectory, fileName);

            File.Create(filePath).Dispose();

            using (FileStream streamToCompress = File.Create(archivePath))
            {
                using GZipStream compressorStream = new GZipStream(streamToCompress, CompressionMode.Compress);
                TarFile.CreateFromDirectory(sourceDirectory, compressorStream, includeBaseDirectory: false);
            }
            FileInfo fileInfo = new FileInfo(archivePath);

            Assert.True(fileInfo.Exists);
            Assert.True(fileInfo.Length > 0);

            using (FileStream streamToDecompress = File.OpenRead(archivePath))
            {
                using GZipStream decompressorStream = new GZipStream(streamToDecompress, CompressionMode.Decompress);
                TarFile.ExtractToDirectory(decompressorStream, destinationDirectory, overwriteFiles: true);
                Assert.True(File.Exists(filePath));
            }
        }
Example #18
0
        private void Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType entryType)
        {
            using TempDirectory root = new TempDirectory();

            string linkName   = "link";
            string targetName = "target";
            string targetPath = Path.Join(root.Path, targetName);

            File.Create(targetPath).Dispose();

            using MemoryStream archive = new MemoryStream();
            using (TarWriter writer = new TarWriter(archive, TarFormat.Ustar, leaveOpen: true))
            {
                UstarTarEntry entry = new UstarTarEntry(entryType, linkName);
                entry.LinkName = targetPath;
                writer.WriteEntry(entry);
            }

            archive.Seek(0, SeekOrigin.Begin);

            TarFile.ExtractToDirectory(archive, root.Path, overwriteFiles: false);

            Assert.Equal(2, Directory.GetFileSystemEntries(root.Path).Count());
        }
Example #19
0
        public void UnixFileModes(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 = TestPermission1;
                writer.WriteEntry(dir);

                PaxTarEntry file = new PaxTarEntry(TarEntryType.RegularFile, "file");
                file.Mode = TestPermission2;
                writer.WriteEntry(file);

                // Archive has no entry for missing_parent.
                PaxTarEntry missingParentDir = new PaxTarEntry(TarEntryType.Directory, "missing_parent/dir");
                missingParentDir.Mode = TestPermission3;
                writer.WriteEntry(missingParentDir);

                // out_of_order_parent/file entry comes before out_of_order_parent entry.
                PaxTarEntry outOfOrderFile = new PaxTarEntry(TarEntryType.RegularFile, "out_of_order_parent/file");
                writer.WriteEntry(outOfOrderFile);

                PaxTarEntry outOfOrderDir = new PaxTarEntry(TarEntryType.Directory, "out_of_order_parent");
                outOfOrderDir.Mode = TestPermission4;
                writer.WriteEntry(outOfOrderDir);
            }

            string dirPath              = Path.Join(destination.Path, "dir");
            string filePath             = Path.Join(destination.Path, "file");
            string missingParentPath    = Path.Join(destination.Path, "missing_parent");
            string missingParentDirPath = Path.Join(missingParentPath, "dir");
            string outOfOrderDirPath    = Path.Join(destination.Path, "out_of_order_parent");

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

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

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

            Assert.True(File.Exists(filePath), $"{filePath}' does not exist.");
            AssertFileModeEquals(filePath, TestPermission2);

            // Missing parents are created with CreateDirectoryDefaultMode.
            Assert.True(Directory.Exists(missingParentPath), $"{missingParentPath}' does not exist.");
            AssertFileModeEquals(missingParentPath, CreateDirectoryDefaultMode);

            Assert.True(Directory.Exists(missingParentDirPath), $"{missingParentDirPath}' does not exist.");
            AssertFileModeEquals(missingParentDirPath, TestPermission3);

            // Directory modes that are out-of-order are still applied.
            Assert.True(Directory.Exists(outOfOrderDirPath), $"{outOfOrderDirPath}' does not exist.");
            AssertFileModeEquals(outOfOrderDirPath, TestPermission4);
        }
Example #20
0
 public void UnreadableStream_Throws()
 {
     using MemoryStream archive     = new MemoryStream();
     using WrappedStream unreadable = new WrappedStream(archive, canRead: false, canWrite: true, canSeek: true);
     Assert.Throws <IOException>(() => TarFile.ExtractToDirectory(unreadable, destinationDirectoryName: "path", overwriteFiles: false));
 }
Example #21
0
 public void InvalidPath_Throws()
 {
     using MemoryStream archive = new MemoryStream();
     Assert.Throws <ArgumentNullException>(() => TarFile.ExtractToDirectory(archive, destinationDirectoryName: null, overwriteFiles: false));
     Assert.Throws <ArgumentException>(() => TarFile.ExtractToDirectory(archive, destinationDirectoryName: string.Empty, overwriteFiles: false));
 }
Example #22
0
 public void NullStream_Throws()
 {
     Assert.Throws <ArgumentNullException>(() => TarFile.ExtractToDirectory(source: null, destinationDirectoryName: "path", overwriteFiles: false));
 }
Example #23
0
        /// <summary>
        ///     Upgrade the package, with the understanding that it is located in the Asset database.
        /// </summary>
        private static void UpgradeAssetDatabase()
        {
            // Get a temporary file
            // TODO: This will need to be changed for newer .NET (System.IO.GetTempFileName())
            string tempFile = Path.GetTempFileName();

            // Download the file
            EditorUtility.DisplayProgressBar("GDX", "Downloading Update ...", 0.25f);
            try
            {
#if UNITY_2020_2_OR_NEWER
                using WebClient webClient = new WebClient();
                webClient.DownloadFile(GitHubLatestUri + UpdatePackageDefinition.version + ".tar.gz",
                                       tempFile);
#else
                using (WebClient webClient = new WebClient())
                {
                    webClient.DownloadFile(GitHubLatestUri + UpdatePackageDefinition.version + ".tar.gz",
                                           tempFile);
                }
#endif
            }
            catch (Exception e)
            {
                // We will end up here if the formulated Uri is bad.
                Debug.LogWarning(e.Message);
                return;
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }

            string tempExtractFolder = Path.Combine(Path.GetTempPath(), PackageProvider.PackageName);

            // Remove previous upgrade folder (if it exists)
            if (Directory.Exists(tempExtractFolder))
            {
                Directory.Delete(tempExtractFolder, true);
            }

            Platform.EnsureFolderHierarchyExists(tempExtractFolder);

            // Extract downloaded tarball to the temp folder
            TarFile.ExtractToDirectory(tempFile, tempExtractFolder, true);

            // Get desired target placement
            string targetPath = Path.GetDirectoryName(LocalPackage.PackageManifestPath);

            // Handle VCS
            if (Provider.enabled && Provider.isActive)
            {
                AssetList checkoutAssets = VersionControl.GetAssetListFromFolder(targetPath);
                Task      checkoutTask   = Provider.Checkout(checkoutAssets, CheckoutMode.Both);
                checkoutTask.Wait();
            }

            // Remove all existing content
            if (targetPath != null)
            {
                try
                {
                    AssetDatabase.StartAssetEditing();
                    Directory.Delete(targetPath, true);

                    // Drop in new content
                    Directory.Move(
                        Path.Combine(tempExtractFolder, "GDX-" + UpdatePackageDefinition.version),
                        targetPath);

                    AssetDatabase.ImportAsset(LocalPackage.PackageAssetPath);
                }
                finally
                {
                    AssetDatabase.StopAssetEditing();
                }
            }
        }