/// <summary> /// Generates a signature stream for the given file and compares it with an existing signature stream, if one exists. /// </summary> /// <param name="fs">The file to examine, the filestream should be at position 0</param> /// <param name="s">The full name of the file</param> /// <param name="signaturefile">The signature archive file</param> /// <returns>The signature stream if the file is new or modified, null if the file has not been modified</returns> private System.IO.Stream ProccessDiff(System.IO.Stream fs, string s, Library.Interface.ICompression signaturefile) { string relpath = GetRelativeName(s); m_examinedfilesize += fs.Length; m_examinedfiles++; System.IO.MemoryStream ms = new MemoryStream(); SharpRSync.ChecksumFileWriter ws = new Duplicati.Library.SharpRSync.ChecksumFileWriter(ms); //Expand the memorystream to contain all bytes, which avoids re-allocation ms.Capacity = Math.Max(ws.BytesGeneratedForSignature((long)(fs.Length * FILESIZE_GROW_MARGIN_MULTIPLIER)), ms.Capacity); ws.AddStream(fs); ms.Position = 0; if (!m_oldSignatures.ContainsKey(relpath)) { m_newfiles.Add(s, null); return ms; } else { bool equals; //File exists in archive, check if signature has changed using (System.IO.Stream s2 = m_oldSignatures[relpath].OpenRead(relpath)) equals = Utility.Utility.CompareStreams(s2, ms, false); ms.Position = 0; if (!equals) { //Yes, changed, return the signature stream m_modifiedFiles.Add(s, null); return ms; } else { //No changes, discard the signature stream ms.Close(); ms.Dispose(); m_oldSignatures.Remove(relpath); return null; } } }
/// <summary> /// Generates a signature, and writes it to the stream /// </summary> /// <param name="input">The stream to create the signature for</param> /// <param name="output">The stream to write the signature into</param> public static void GenerateSignature(Stream input, Stream output) { SharpRSync.ChecksumFileWriter cs = new Duplicati.Library.SharpRSync.ChecksumFileWriter(output); cs.AddStream(input); }