async Task <bool> ExtractPartAndValidate(PartialZipDownload part, Stream partInputStream, string cacheDirectory) { string fileHash = null; var outputPath = GetOutputPath(cacheDirectory, part); using (var iis = new System.IO.Compression.DeflateStream(partInputStream, System.IO.Compression.CompressionMode.Decompress)) //using (var iis = new ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream (partInputStream, new ICSharpCode.SharpZipLib.Zip.Compression.Inflater (true))) using (var fs = File.Open(outputPath, FileMode.Create)) { await iis.CopyToAsync(fs).ConfigureAwait(false); await fs.FlushAsync().ConfigureAwait(false); fs.Seek(0, SeekOrigin.Begin); fileHash = DownloadUtils.HashSha256(fs); LogDebugMessage("Hash of Downloaded File: {0}", fileHash); fs.Close(); } if (!string.IsNullOrEmpty(part.Sha256) && !part.Sha256.Equals(fileHash, StringComparison.InvariantCultureIgnoreCase)) { // TODO: HANDLE LogMessage("File SHA256 Hash was invalid, deleting file: {0}", part.ToFile); File.Delete(outputPath); return(false); } // Run through our AAR fixups if it's android if (IsAndroid) { AndroidAarFixups.FixupAar(outputPath, AndroidFixManifests, Log); } return(true); }
async Task <bool> MakeSureLibraryIsInPlace(XamarinBuildDownload xbd, CancellationToken token) { // Skip extraction if the file is already in place var flagFile = xbd.DestinationDir + ".unpacked"; if (File.Exists(flagFile)) { return(true); } try { Directory.CreateDirectory(xbd.DestinationDir); } catch (Exception ex) { LogCodedError(ThisOrThat(xbd.CustomErrorCode, ErrorCodes.DirectoryCreateFailed), ThisOrThat(xbd.CustomErrorMessage, () => string.Format("Failed to create directory '{0}'.", xbd.DestinationDir))); LogMessage("Directory creation failure reason: " + ex.ToString(), MessageImportance.High); return(false); } var lockFile = xbd.DestinationDir + ".locked"; using (var lockStream = DownloadUtils.ObtainExclusiveFileLock(lockFile, Token, TimeSpan.FromSeconds(xbd.ExclusiveLockTimeout), this)) { if (lockStream == null) { LogCodedError(ErrorCodes.ExclusiveLockTimeout, "Timed out waiting for exclusive file lock on: {0}", lockFile); LogMessage("Timed out waiting for an exclusive file lock on: " + lockFile, MessageImportance.High); return(false); } if (!File.Exists(xbd.CacheFile) || !IsValidDownload(xbd.DestinationDir + ".sha256", xbd.CacheFile, xbd.Sha256)) { try { int progress = -1; DownloadProgressChangedEventHandler downloadHandler = (o, e) => { if (e.ProgressPercentage % 10 != 0 || progress == e.ProgressPercentage) { return; } progress = e.ProgressPercentage; LogMessage( "\t({0}/{1}b), total {2:F1}%", e.BytesReceived, e.TotalBytesToReceive, e.ProgressPercentage ); }; using (var client = new WebClient()) { client.DownloadProgressChanged += downloadHandler; LogMessage(" Downloading {0} to {1}", xbd.Url, xbd.CacheFile); client.DownloadFileTaskAsync(xbd.Url, xbd.CacheFile).Wait(token); // Run through our AAR fixups if it's android if (IsAndroid) { AndroidAarFixups.FixupAar(xbd.CacheFile, AndroidFixManifests, Log); } LogMessage(" Downloading Complete"); client.DownloadProgressChanged -= downloadHandler; } } catch (Exception e) { LogCodedError(ThisOrThat(xbd.CustomErrorCode, ErrorCodes.DownloadFailed), ThisOrThat(xbd.CustomErrorMessage, () => string.Format("Download failed. Please download {0} to a file called {1}.", xbd.Url, xbd.CacheFile))); LogMessage("Download failure reason: " + e.GetBaseException().Message, MessageImportance.High); File.Delete(xbd.CacheFile); return(false); } } if (!File.Exists(xbd.CacheFile)) { LogCodedError(ThisOrThat(xbd.CustomErrorCode, ErrorCodes.DownloadedFileMissing), ThisOrThat(xbd.CustomErrorMessage, () => string.Format("Downloaded file '{0}' is missing.", xbd.CacheFile))); return(false); } if (xbd.Kind == ArchiveKind.Uncompressed) { var uncompressedCacheFile = xbd.CacheFile; if (!string.IsNullOrEmpty(xbd.ToFile)) { uncompressedCacheFile = xbd.ToFile; } File.Move(xbd.CacheFile, Path.Combine(xbd.DestinationDir, Path.GetFileName(uncompressedCacheFile))); File.WriteAllText(flagFile, "This marks that the extraction completed successfully"); return(true); } else { if (await ExtractArchive(xbd, flagFile, token)) { File.WriteAllText(flagFile, "This marks that the extraction completed successfully"); return(true); } } } // We will attempt to delete the lock file when we're done try { if (File.Exists(lockFile)) { File.Delete(lockFile); } } catch { } return(false); }