private void CopyEntryDataDirect(ZipUpdate update, Stream stream, bool updateCrc, ref long destinationPosition, ref long sourcePosition) { var bytesToCopy = update.Entry.CompressedSize; // NOTE: Compressed size is updated elsewhere. var crc = new Crc32(); var buffer = GetBuffer(); var targetBytes = bytesToCopy; long totalBytesRead = 0; int bytesRead; do { var readSize = buffer.Length; if (bytesToCopy < readSize) { readSize = (int) bytesToCopy; } stream.Position = sourcePosition; bytesRead = stream.Read(buffer, 0, readSize); if (bytesRead > 0) { if (updateCrc) { crc.Update(buffer, 0, bytesRead); } stream.Position = destinationPosition; stream.Write(buffer, 0, bytesRead); destinationPosition += bytesRead; sourcePosition += bytesRead; bytesToCopy -= bytesRead; totalBytesRead += bytesRead; } } while ((bytesRead > 0) && (bytesToCopy > 0)); if (totalBytesRead != targetBytes) { throw new ZipException(string.Format("Failed to copy bytes expected {0} read {1}", targetBytes, totalBytesRead)); } if (updateCrc) { update.OutEntry.Crc = crc.Value; } }
/// <summary> /// Upgrades the installed files log entries. /// </summary> /// <remarks> /// This analyses the mods and determines, as best as possible, who owns which files, and attempts /// to reconstruct the install order. It populates the overwrites folder with the files that, as far /// as can be determined, belong there. This resulting information is then put in the new install log. /// </remarks> /// <param name="p_xmlModInstallLog">The current mod install log we are parsing to upgrade.</param> /// <param name="p_strModInstallLogPath">The path to the current mod install log.</param> /// <param name="p_strModBaseName">The base name of the mod whose install log is being parsed.</param> private void UpgradeInstalledFiles(XmlDocument p_xmlModInstallLog, fomod p_fomodMod, string p_strModBaseName) { var intDataPathStartPos = Program.GameMode.PluginsPath.Trim(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar).Length + 1; var xnlFiles = p_xmlModInstallLog.SelectNodes("descendant::installedFiles/*"); foreach (XmlNode xndFile in xnlFiles) { var strFile = xndFile.InnerText; if (!File.Exists(strFile)) { continue; } var strDataRelativePath = strFile.Substring(intDataPathStartPos); var crcDiskFile = new Crc32(); var crcFomodFile = new Crc32(); crcDiskFile.Update(File.ReadAllBytes(strFile)); if (!p_fomodMod.ContainsFile(strDataRelativePath)) { //we don't know if this mod owns the file, so let's assume // it doesn't //put this mod's file into the overwrites directory. // we can't get the original file from the fomod, // so we'll use the existing file instead. this isn't // strictly correct, but it is inline with the behaviour // of the fomm version we are upgrading from var strDirectory = Path.GetDirectoryName(strDataRelativePath); var strBackupPath = Path.Combine(Program.GameMode.OverwriteDirectory, strDirectory); var strModKey = InstallLog.Current.GetModKey(p_strModBaseName); if (!Directory.Exists(strBackupPath)) { FileManager.CreateDirectory(strBackupPath); } strBackupPath = Path.Combine(strBackupPath, strModKey + "_" + Path.GetFileName(strDataRelativePath)); FileManager.Copy(Path.Combine(Program.GameMode.PluginsPath, strDataRelativePath), strBackupPath, true); InstallLog.Current.PrependDataFile(p_strModBaseName, strDataRelativePath); //however, it may own the file, so let's make it the default owner for now // unless we already know who the owner is if (!FileOwnerIsKnown(strDataRelativePath)) { m_dicDefaultFileOwners[strDataRelativePath] = p_strModBaseName; } continue; } var bteFomodFile = p_fomodMod.GetFileContents(strDataRelativePath); crcFomodFile.Update(bteFomodFile); if (!crcDiskFile.Value.Equals(crcFomodFile.Value) || FileOwnerIsKnown(strDataRelativePath)) { //either: // 1) another mod owns the file // 2) according to the crc we own this file, however we have already found // an owner. this could happen beacue two mods use the same version // of a file, or there is a crc collision. //either way, put this mod's file into // the overwrites directory var strDirectory = Path.GetDirectoryName(strDataRelativePath); var strBackupPath = Path.Combine(Program.GameMode.OverwriteDirectory, strDirectory); var strModKey = InstallLog.Current.GetModKey(p_strModBaseName); if (!Directory.Exists(strBackupPath)) { FileManager.CreateDirectory(strBackupPath); } strBackupPath = Path.Combine(strBackupPath, strModKey + "_" + Path.GetFileName(strDataRelativePath)); FileManager.WriteAllBytes(strBackupPath, bteFomodFile); InstallLog.Current.PrependDataFile(p_strModBaseName, strDataRelativePath); } else { //this mod owns the file, so append it to the list of installing mods InstallLog.Current.AddDataFile(p_strModBaseName, strDataRelativePath); //we also have to displace the mod that is currently the default owner if (m_dicDefaultFileOwners.ContainsKey(strDataRelativePath)) { m_dicDefaultFileOwners.Remove(strDataRelativePath); } } if (ProgressWorker.Cancelled()) { return; } ProgressWorker.StepItemProgress(); } }
private void CopyBytes(ZipUpdate update, Stream destination, Stream source, long bytesToCopy, bool updateCrc) { if (destination == source) { throw new InvalidOperationException("Destination and source are the same"); } // NOTE: Compressed size is updated elsewhere. var crc = new Crc32(); var buffer = GetBuffer(); var targetBytes = bytesToCopy; long totalBytesRead = 0; int bytesRead; do { var readSize = buffer.Length; if (bytesToCopy < readSize) { readSize = (int) bytesToCopy; } bytesRead = source.Read(buffer, 0, readSize); if (bytesRead > 0) { if (updateCrc) { crc.Update(buffer, 0, bytesRead); } destination.Write(buffer, 0, bytesRead); bytesToCopy -= bytesRead; totalBytesRead += bytesRead; } } while ((bytesRead > 0) && (bytesToCopy > 0)); if (totalBytesRead != targetBytes) { throw new ZipException(string.Format("Failed to copy bytes expected {0} read {1}", targetBytes, totalBytesRead)); } if (updateCrc) { update.OutEntry.Crc = crc.Value; } }
private static bool ReplaceShader(string file, string shader, byte[] newdata, out byte[] OldData, uint crc) { var tempshader = Path.Combine(Program.tmpPath, "tempshader"); var timeStamp = File.GetLastWriteTime(file); File.Delete(tempshader); File.Move(file, tempshader); var br = new BinaryReader(File.OpenRead(tempshader), Encoding.Default); var bw = new BinaryWriter(File.Create(file), Encoding.Default); bw.Write(br.ReadInt32()); var num = br.ReadInt32(); bw.Write(num); var sizeoffset = br.BaseStream.Position; bw.Write(br.ReadInt32()); var found = false; OldData = null; for (var i = 0; i < num; i++) { var name = br.ReadChars(0x100); var size = br.ReadInt32(); var data = br.ReadBytes(size); bw.Write(name); var sname = ""; for (var i2 = 0; i2 < 100; i2++) { if (name[i2] == '\0') { break; } sname += name[i2]; } if (!found && sname == shader) { var ccrc = new Crc32(); ccrc.Update(data); if (crc == 0 || ccrc.Value == crc) { bw.Write(newdata.Length); bw.Write(newdata); found = true; OldData = data; } else { bw.Write(size); bw.Write(data); } } else { bw.Write(size); bw.Write(data); } } bw.BaseStream.Position = sizeoffset; bw.Write((int) (bw.BaseStream.Length - 12)); br.Close(); bw.Close(); File.Delete(tempshader); File.SetLastWriteTime(file, timeStamp); return found; }