private Manifest GenerateManifest(string path, string?subdir) { var builder = new ManifestBuilder(_algorithm); if (Directory.Exists(path)) { if (!string.IsNullOrEmpty(subdir)) { throw new OptionException(Resources.TooManyArguments + Environment.NewLine + subdir.EscapeArgument(), null); } Handler.RunTask(new ReadDirectory(path, builder)); return(builder.Manifest); } else if (File.Exists(path)) { var extractor = ArchiveExtractor.For(Archive.GuessMimeType(path), Handler); Handler.RunTask(new ReadFile(path, stream => extractor.Extract(builder, stream, subdir))); return(builder.Manifest); } else { throw new FileNotFoundException(string.Format(Resources.FileOrDirNotFound, path)); } }
private Manifest GenerateManifest(string path, string?subdir) { if (Directory.Exists(path)) { if (!string.IsNullOrEmpty(subdir)) { throw new OptionException(Resources.TooManyArguments + Environment.NewLine + subdir.EscapeArgument(), null); } var generator = new ManifestGenerator(path, _algorithm); Handler.RunTask(generator); return(generator.Manifest); } else if (File.Exists(path)) { using var tempDir = new TemporaryDirectory("0install"); using (var extractor = ArchiveExtractor.Create(path, tempDir, Archive.GuessMimeType(path))) { extractor.Extract = subdir; Handler.RunTask(extractor); } var generator = new ManifestGenerator(tempDir, _algorithm); Handler.RunTask(generator); return(generator.Manifest); } else { throw new FileNotFoundException(string.Format(Resources.FileOrDirNotFound, path)); } }
/// <summary> /// Downloads a specific file. /// </summary> public async Task DownloadAndExtract(DownloadProgressChangedEventHandler progressChanged) { // Start the modification download. byte[] data; using (WebClient client = new WebClient()) { client.DownloadProgressChanged += progressChanged; data = await client.DownloadDataTaskAsync(Uri); } /* Extract to Temp Directory */ string temporaryDirectory = GetTemporaryDirectory(); var archiveExtractor = new ArchiveExtractor(); await archiveExtractor.ExtractPackageAsync(data, temporaryDirectory); /* Get name of package. */ var configReader = new ConfigReader <ModConfig>(); var configs = configReader.ReadConfigurations(temporaryDirectory, ModConfig.ConfigFileName); var loaderConfig = LoaderConfigReader.ReadConfiguration(); foreach (var config in configs) { string configId = config.Object.ModId; string configDirectory = Path.GetDirectoryName(config.Path); string targetDirectory = Path.Combine(loaderConfig.ModConfigDirectory, configId); IOEx.MoveDirectory(configDirectory, targetDirectory); } Directory.Delete(temporaryDirectory, true); }
private static async Task Main(string[] args) { var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).AppSettings.Settings; await Parser.Default.ParseArguments <GenerateArchiveOptions, ExtractArchiveOptions, ModifyDllOptions>(args) .MapResult( (GenerateArchiveOptions opts) => GenerateArchive(opts), (ExtractArchiveOptions opts) => ExtractArchive(opts), (ModifyDllOptions opts) => ModifyDll(opts), errors => Task.FromResult(0)); async Task ModifyDll(ModifyDllOptions opts) { var csDir = opts.CsgoDirectory ?? config["csgoDirectory"].Value; WriteResult(await DllModifier.ModifyDll(csDir)); } async Task GenerateArchive(GenerateArchiveOptions opts) { var inputDir = opts.DirectoryPath ?? config["archiveDirectory"].Value; var outputDir = opts.OutputPath ?? config["outputDirectory"].Value; WriteResult(await ArchiveGenerator.GenerateArchive(opts.DirectoryPath, opts.OutputPath)); } async Task ExtractArchive(ExtractArchiveOptions opts) { var csDir = opts.DirectoryPath ?? config["csgoDirectory"].Value; var outputDir = opts.OutputPath ?? config["archiveDirectory"].Value; WriteResult(await ArchiveExtractor.ExtractArchive(csDir, outputDir)); } }
/// <inheritdoc/> public string AddArchives(IEnumerable <ArchiveFileInfo> archiveInfos, ManifestDigest manifestDigest, ITaskHandler handler) { #region Sanity checks if (archiveInfos == null) { throw new ArgumentNullException(nameof(archiveInfos)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } if (manifestDigest.Best == null) { throw new ArgumentException("No known digest method", nameof(manifestDigest)); } #endregion if (Contains(manifestDigest)) { throw new ImplementationAlreadyInStoreException(manifestDigest); } Log.Info("Caching implementation: " + manifestDigest.Best); // Extract to temporary directory inside the cache so it can be validated safely (no manipulation of directory while validating) string tempDir = GetTempDir(); try { // Extract archives "over each other" in order foreach (var archiveInfo in archiveInfos) { try { using (var extractor = ArchiveExtractor.Create(archiveInfo.Path, tempDir, archiveInfo.MimeType, archiveInfo.StartOffset)) { extractor.SubDir = archiveInfo.SubDir; extractor.Destination = archiveInfo.Destination; extractor.Tag = manifestDigest; handler.RunTask(extractor); } } #region Error handling catch (IOException ex) { string source = archiveInfo.OriginalSource?.ToStringRfc() ?? archiveInfo.Path; throw new IOException(string.Format(Resources.FailedToExtractArchive, source), ex); } #endregion } return(VerifyAndAdd(Path.GetFileName(tempDir), manifestDigest, handler)); } finally { DeleteTempDir(tempDir); } }
public void ShouldExtractPackageToTemporaryFolder() { var compressionUtilityMock = new Mock <ICompressionUtility>(); var uuid = "d1c9102e-7106-4355-a4a4-0c9b7f9b3541"; var inputFilename = "c:\\users\\johnsmith\\my documents\\" + uuid + ".tar"; var archiveExtraction = new ArchiveExtractor(compressionUtilityMock.Object).Extract(inputFilename); archiveExtraction.WorkingDirectory.Should().Be(ArchiveExtractor.TemporaryFolder + Path.DirectorySeparatorChar + uuid); archiveExtraction.Uuid.Should().Be(uuid); }
public void Hardlink() { using var tempDir = new TemporaryDirectory("0install-test-archive"); var builder = new DirectoryBuilder(tempDir); using var stream = typeof(ArchiveExtractorTestBase).GetEmbeddedStream(FileName); ArchiveExtractor.For(MimeType, new SilentTaskHandler()) .Extract(builder, stream); FileUtils.AreHardlinked(Path.Combine(tempDir, "hardlink"), Path.Combine(tempDir, "subdir1", "regular")) .Should().BeTrue(because: "'regular' and 'hardlink' should be hardlinked together"); }
private void ExtractOriginalData(string gameDirectory, string workingDirectory, string file) { string sourceFile = Path.Combine(gameDirectory, file); string targetDirectory = Path.Combine(workingDirectory, Path.GetFileName(file) + ".extracted"); string infoDirectory = Path.Combine(workingDirectory, Path.GetFileName(file) + ".info"); using (IFileDataWrapper data = StreamFileDataWrapper.FromFile(sourceFile)) { ArchiveExtractor archiveExtractor = new ArchiveExtractor(targetDirectory, infoDirectory, data); archiveExtractor.Unpack(); } }
private void BuildImplementation(IBuilder builder) { for (int i = 0; i < (AdditionalArgs.Count + 1) / 3; i++) { string path = AdditionalArgs[i * 3 + 1]; string mimeType = (AdditionalArgs.Count > i * 3 + 3) ? AdditionalArgs[i * 3 + 3] : Archive.GuessMimeType(AdditionalArgs[i * 3 + 1]); string?subDir = (AdditionalArgs.Count > i * 3 + 2) ? AdditionalArgs[i * 3 + 2] : null; var extractor = ArchiveExtractor.For(mimeType, Handler); Handler.RunTask(new ReadFile(path, stream => extractor.Extract(builder, stream, subDir))); } }
/// <summary> /// Downloads a specific file. /// </summary> public async Task DownloadAndExtract(DownloadProgressChangedEventHandler progressChanged) { // Start the modification download. byte[] data; using (WebClient client = new WebClient()) { client.DownloadProgressChanged += progressChanged; data = await client.DownloadDataTaskAsync(Uri); } /* Extract to Temp Directory */ string temporaryDirectory = GetTemporaryDirectory(); var archiveExtractor = new ArchiveExtractor(); await archiveExtractor.ExtractPackageAsync(data, temporaryDirectory); /* Get name of package. */ var configs = ConfigReader <ModConfig> .ReadConfigurations(temporaryDirectory, ModConfig.ConfigFileName, default, int.MaxValue);
/// <summary> /// Applies a <see cref="Archive"/> to a <see cref="TemporaryDirectory"/>. /// </summary> /// <param name="step">The <see cref="Archive"/> to apply.</param> /// <param name="localPath">The local path of the archive.</param> /// <param name="workingDir">The <see cref="TemporaryDirectory"/> to apply the changes to.</param> /// <param name="handler">A callback object used when the the user needs to be informed about progress.</param> /// <param name="tag">The <see cref="ITaskHandler"/> tag used by <paramref name="handler"/>; can be <c>null</c>.</param> /// <exception cref="IOException">A path specified in <paramref name="step"/> is illegal.</exception> public static void Apply([NotNull] this Archive step, [NotNull] string localPath, [NotNull] TemporaryDirectory workingDir, [NotNull] ITaskHandler handler, [CanBeNull] object tag = null) { #region Sanity checks if (step == null) { throw new ArgumentNullException(nameof(step)); } if (string.IsNullOrEmpty(localPath)) { throw new ArgumentNullException(nameof(localPath)); } if (workingDir == null) { throw new ArgumentNullException(nameof(workingDir)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } #endregion #region Path validation if (!string.IsNullOrEmpty(step.Destination)) { string destination = FileUtils.UnifySlashes(step.Destination); if (FileUtils.IsBreakoutPath(destination)) { throw new IOException(string.Format(Resources.RecipeInvalidPath, destination)); } } #endregion if (string.IsNullOrEmpty(step.MimeType)) { throw new IOException(Resources.UnknownArchiveType); } using (var extractor = ArchiveExtractor.Create(localPath, workingDir, step.MimeType)) { extractor.SubDir = step.Extract; extractor.Destination = FileUtils.UnifySlashes(step.Destination); extractor.Tag = tag; handler.RunTask(extractor); } }
private void BuildImplementation(IBuilder builder) { for (int i = 0; i < (AdditionalArgs.Count + 1) / 3; i++) { string path = AdditionalArgs[i * 3 + 1]; string mimeType = (AdditionalArgs.Count > i * 3 + 3) ? AdditionalArgs[i * 3 + 3] : Archive.GuessMimeType(AdditionalArgs[i * 3 + 1]); string?subDir = (AdditionalArgs.Count > i * 3 + 2) ? AdditionalArgs[i * 3 + 2] : null; void Callback(Stream stream) => ArchiveExtractor.For(mimeType, Handler) .Extract(builder, stream, subDir); Handler.RunTask( Uri.TryCreate(path, UriKind.Absolute, out var uri) && !uri.IsFile ? new DownloadFile(uri, Callback) : new ReadFile(path, Callback)); } }
/// <summary> /// Applies a <see cref="Archive"/> to a <see cref="TemporaryDirectory"/>. /// </summary> /// <param name="step">The <see cref="Archive"/> to apply.</param> /// <param name="localPath">The local path of the archive.</param> /// <param name="workingDir">The <see cref="TemporaryDirectory"/> to apply the changes to.</param> /// <param name="handler">A callback object used when the the user needs to be informed about progress.</param> /// <param name="tag">A tag used to associate composite task with a specific operation; can be null.</param> /// <exception cref="IOException">A path specified in <paramref name="step"/> is illegal.</exception> /// <exception cref="ArgumentException"><see cref="Archive.Normalize"/> was not called for <paramref name="step"/>.</exception> public static void Apply(this Archive step, string localPath, TemporaryDirectory workingDir, ITaskHandler handler, object?tag = null) { #region Sanity checks if (step == null) { throw new ArgumentNullException(nameof(step)); } if (string.IsNullOrEmpty(localPath)) { throw new ArgumentNullException(nameof(localPath)); } if (workingDir == null) { throw new ArgumentNullException(nameof(workingDir)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } #endregion if (!string.IsNullOrEmpty(step.Destination)) { string destination = FileUtils.UnifySlashes(step.Destination); if (FileUtils.IsBreakoutPath(destination)) { throw new IOException(string.Format(Resources.RecipeInvalidPath, destination)); } } using var extractor = ArchiveExtractor.Create( localPath, workingDir, step.MimeType ?? throw new ArgumentException($"{nameof(step.Normalize)} was not called.", nameof(step)), step.StartOffset); extractor.Extract = step.Extract; extractor.TargetSuffix = FileUtils.UnifySlashes(step.Destination); extractor.Tag = tag; handler.RunTask(extractor); }
protected async Task <bool> DownloadAndExtractAsync(string url, string destination, ArchiveExtractor extractor, CancellationToken cancellationToken) { Log.Verbose($"Downloading from '{url}'"); HttpResponseMessage result; try { result = await Http.DefaultHttpClient.GetAsync(url, cancellationToken); } catch (HttpRequestException ex) { Log.Error($"Downloading asset failed: {ex.Message}"); return(false); } if (!result.IsSuccessStatusCode) { Log.Error($"Failed to download '{url}'"); throw new InvalidOperationException("Installation failed"); } var filename = Path.GetFileName(url); var ext = filename.EndsWith(".tar.gz", StringComparison.OrdinalIgnoreCase) ? ".tar.gz" : Path.GetExtension(filename); using (var tmp = new TempFile(ext)) using (var stream = new FileStream(tmp.Path, FileMode.Create)) { await result.Content.CopyToAsync(stream); Log.Verbose($"Extracting '{filename}' to '{destination}'"); return(extractor(tmp.Path, destination)); } }
void DownloadEmulator() { if (!Directory.Exists(ServiceTools.Storage.Source.PathEmulator)) { Directory.CreateDirectory(ServiceTools.Storage.Source.PathEmulator); WebDownloadClient download = new WebDownloadClient(0, "https://www.zerpico.ru/retrolauncher/mednafen.zip"); download.FileName = Path.Combine(ServiceTools.Storage.Source.PathEmulator, download.Url.ToString().Substring(download.Url.ToString().LastIndexOf("/") + 1)); download.DownloadCompleted += ((e, a) => { ArchiveExtractor.ExtractAll(download.FileName, ServiceTools.Storage.Source.PathEmulator, true); System.Windows.Application.Current.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, (Action) delegate() { DownloadManager.Instance.ClearDownload(0); }); }); string filePath = download.FileName; string tempPath = filePath + ".tmp"; download.CheckUrl(); if (download.HasError) { return; } download.TempDownloadPath = tempPath; download.AddedOn = DateTime.UtcNow; download.CompletedOn = DateTime.MinValue; // Add the download to the downloads list DownloadManager.Instance.DownloadsList.Add(download); download.Start(); } }
/// <summary> /// Executes a <see cref="Recipe"/>. /// </summary> /// <param name="recipe">The recipe to execute.</param> /// <param name="manifestDigest">The digest the result of the recipe should produce.</param> /// <exception cref="OperationCanceledException">A download or IO task was canceled from another thread.</exception> /// <exception cref="WebException">A file could not be downloaded from the internet.</exception> /// <exception cref="NotSupportedException">A file format, protocal, etc. is unknown or not supported.</exception> /// <exception cref="IOException">A downloaded file could not be written to the disk or extracted.</exception> /// <exception cref="ImplementationAlreadyInStoreException">There is already an <see cref="Implementation"/> with the specified <paramref name="manifestDigest"/> in the store.</exception> /// <exception cref="UnauthorizedAccessException">Write access to <see cref="IStore"/> is not permitted.</exception> /// <exception cref="DigestMismatchException">An <see cref="Implementation"/>'s <see cref="Archive"/>s don't match the associated <see cref="ManifestDigest"/>.</exception> private void Cook([NotNull] Recipe recipe, ManifestDigest manifestDigest) { Handler.CancellationToken.ThrowIfCancellationRequested(); // Fail fast on unsupported archive type foreach (var archive in recipe.Steps.OfType <Archive>()) { ArchiveExtractor.VerifySupport(archive.MimeType); } var downloadedFiles = new List <TemporaryFile>(); try { foreach (var downloadStep in recipe.Steps.OfType <DownloadRetrievalMethod>()) { downloadedFiles.Add(Download(downloadStep, tag: manifestDigest)); } // More efficient special-case handling for Archive-only cases if (recipe.Steps.All(step => step is Archive)) { ApplyArchives(recipe.Steps.Cast <Archive>().ToList(), downloadedFiles, manifestDigest); } else { ApplyRecipe(recipe, downloadedFiles, manifestDigest); } } finally { foreach (var downloadedFile in downloadedFiles) { downloadedFile.Dispose(); } } }
public void TestForZip() { ArchiveExtractor.For(Archive.MimeTypeZip, new SilentTaskHandler()) .Should().BeOfType <ZipExtractor>(); }