public BackupHandler(string backendurl, Options options, BackupResults results) { EMPTY_METADATA = Utility.WrapMetadata(new Dictionary<string, string>(), options); m_options = options; m_result = results; m_backendurl = backendurl; m_attributeFilter = m_options.FileAttributeFilter; m_symlinkPolicy = m_options.SymlinkPolicy; m_blocksize = m_options.Blocksize; m_blockbuffer = new byte[m_options.Blocksize * Math.Max(1, m_options.FileReadBufferSize / m_options.Blocksize)]; m_blocklistbuffer = new byte[m_options.Blocksize]; m_blockhasher = System.Security.Cryptography.HashAlgorithm.Create(m_options.BlockHashAlgorithm); m_filehasher = System.Security.Cryptography.HashAlgorithm.Create(m_options.FileHashAlgorithm); if (m_blockhasher == null) throw new Exception(string.Format(Strings.Foresthash.InvalidHashAlgorithm, m_options.BlockHashAlgorithm)); if (m_filehasher == null) throw new Exception(string.Format(Strings.Foresthash.InvalidHashAlgorithm, m_options.FileHashAlgorithm)); if (!m_blockhasher.CanReuseTransform) throw new Exception(string.Format(Strings.Foresthash.InvalidCryptoSystem, m_options.BlockHashAlgorithm)); if (!m_filehasher.CanReuseTransform) throw new Exception(string.Format(Strings.Foresthash.InvalidCryptoSystem, m_options.FileHashAlgorithm)); if (options.AllowPassphraseChange) throw new Exception(Strings.Foresthash.PassphraseChangeUnsupported); }
public BackupHandler(string backendurl, Options options, BackupResults results) { EMPTY_METADATA = Utility.WrapMetadata(new Dictionary<string, string>(), options); m_options = options; m_result = results; m_backendurl = backendurl; m_attributeFilter = m_options.FileAttributeFilter; m_symlinkPolicy = m_options.SymlinkPolicy; if (options.AllowPassphraseChange) throw new Exception(Strings.Foresthash.PassphraseChangeUnsupported); }
/// <summary> /// Adds a file to the output, /// </summary> /// <param name="filename">The name of the file to record</param> /// <param name="lastModified">The value of the lastModified timestamp</param> /// <param name="database">The database to use</param> /// <param name="streamblockchannel">The channel to write blocks to</param> /// <param name="meta">The metadata ti record</param> private static async Task AddSymlinkToOutputAsync(string filename, DateTime lastModified, IMetahash meta, BackupDatabase database, IWriteChannel <StreamBlock> streamblockchannel) { var metadataid = await AddMetadataToOutputAsync(filename, meta, database, streamblockchannel).ConfigureAwait(false); await database.AddSymlinkEntryAsync(filename, metadataid.Item2, lastModified); }
/// <summary> /// Adds metadata to output, and returns the metadataset ID /// </summary> /// <returns>The metadataset ID.</returns> /// <param name="path">The path for which metadata is processed.</param> /// <param name="meta">The metadata entry.</param> /// <param name="database">The database connection.</param> /// <param name="streamblockchannel">The channel to write streams to.</param> internal static async Task <Tuple <bool, long> > AddMetadataToOutputAsync(string path, IMetahash meta, BackupDatabase database, IWriteChannel <StreamBlock> streamblockchannel) { StreamProcessResult res; using (var ms = new MemoryStream(meta.Blob)) res = await StreamBlock.ProcessStream(streamblockchannel, path, ms, true, CompressionHint.Default); return(await database.AddMetadatasetAsync(res.Streamhash, res.Streamlength, res.Blocksetid)); }
/// <summary> /// Processes the metadata for the given path. /// </summary> /// <returns><c>True</c> if the path should be submitted to more analysis, <c>false</c> if there is nothing else to do</returns> private static async Task <bool> ProcessMetadata(string path, FileAttributes attributes, DateTime lastwrite, Options options, Snapshots.ISnapshotService snapshot, IMetahash emptymetadata, BackupDatabase database, IWriteChannel <StreamBlock> streamblockchannel) { if (snapshot.IsSymlink(path, attributes)) { // Not all reparse points are symlinks. // For example, on Windows 10 Fall Creator's Update, the OneDrive folder (and all subfolders) // are reparse points, which allows the folder to hook into the OneDrive service and download things on-demand. // If we can't find a symlink target for the current path, we won't treat it as a symlink. string symlinkTarget = snapshot.GetSymlinkTarget(path); if (!string.IsNullOrWhiteSpace(symlinkTarget)) { if (options.SymlinkPolicy == Options.SymlinkStrategy.Ignore) { Logging.Log.WriteVerboseMessage(FILELOGTAG, "IgnoreSymlink", "Ignoring symlink {0}", path); return(false); } if (options.SymlinkPolicy == Options.SymlinkStrategy.Store) { var metadata = MetadataGenerator.GenerateMetadata(path, attributes, options, snapshot); if (!metadata.ContainsKey("CoreSymlinkTarget")) { metadata["CoreSymlinkTarget"] = symlinkTarget; } var metahash = Utility.WrapMetadata(metadata, options); await AddSymlinkToOutputAsync(path, DateTime.UtcNow, metahash, database, streamblockchannel).ConfigureAwait(false); Logging.Log.WriteVerboseMessage(FILELOGTAG, "StoreSymlink", "Stored symlink {0}", path); // Don't process further return(false); } } else { Logging.Log.WriteVerboseMessage(FILELOGTAG, "FollowingEmptySymlink", "Treating empty symlink as regular path {0}", path); } } if ((attributes & FileAttributes.Directory) == FileAttributes.Directory) { IMetahash metahash; if (!options.SkipMetadata) { metahash = Utility.WrapMetadata(MetadataGenerator.GenerateMetadata(path, attributes, options, snapshot), options); } else { metahash = emptymetadata; } Logging.Log.WriteVerboseMessage(FILELOGTAG, "AddDirectory", "Adding directory {0}", path); await AddFolderToOutputAsync(path, lastwrite, metahash, database, streamblockchannel).ConfigureAwait(false); return(false); } // Regular file, keep going return(true); }
/// <summary> /// Adds a file to the output, /// </summary> /// <param name="filename">The name of the file to record</param> /// <param name="lastModified">The value of the lastModified timestamp</param> /// <param name="hashlist">The list of hashes that make up the file</param> /// <param name="size">The size of the file</param> /// <param name="fragmentoffset">The offset into a fragment block where the last few bytes are stored</param> /// <param name="metadata">A lookup table with various metadata values describing the file</param> private bool AddSymlinkToOutput(string filename, DateTime scantime, IMetahash meta) { long metadataid; bool r = false; //TODO: If meta.Size > blocksize... r |= AddBlockToOutput(meta.Hash, meta.Blob, 0, (int)meta.Size, CompressionHint.Default, false); r |= m_database.AddMetadataset(meta.Hash, meta.Size, out metadataid, m_transaction); m_database.AddSymlinkEntry(filename, metadataid, scantime, m_transaction); return r; }
/// <summary> /// Adds a file to the output, /// </summary> /// <param name="filename">The name of the file to record</param> /// <param name="lastModified">The value of the lastModified timestamp</param> /// <param name="hashlist">The list of hashes that make up the file</param> /// <param name="size">The size of the file</param> /// <param name="fragmentoffset">The offset into a fragment block where the last few bytes are stored</param> /// <param name="metadata">A lookup table with various metadata values describing the file</param> private void AddFileToOutput(string filename, long size, DateTime scantime, IMetahash metadata, IEnumerable<string> hashlist, string filehash, IEnumerable<string> blocklisthashes) { long metadataid; long blocksetid; //TODO: If metadata.Size > blocksize... AddBlockToOutput(metadata.Hash, metadata.Blob, 0, (int)metadata.Size, CompressionHint.Default, false); m_database.AddMetadataset(metadata.Hash, metadata.Size, out metadataid, m_transaction); m_database.AddBlockset(filehash, size, m_blocksize, hashlist, blocklisthashes, out blocksetid, m_transaction); //m_filesetvolume.AddFile(filename, filehash, size, scantime, metadata.Hash, metadata.Size, blocklisthashes); m_database.AddFile(filename, scantime, blocksetid, metadataid, m_transaction); }
/// <summary> /// Adds a file to the output, /// </summary> /// <param name="filename">The name of the file to record</param> /// <param name="lastModified">The value of the lastModified timestamp</param> private static async Task AddFolderToOutputAsync(string filename, DateTime lastModified, IMetahash meta, BackupDatabase database, IWriteChannel <StreamBlock> streamblockchannel) { var metadataid = await AddMetadataToOutputAsync(filename, meta, database, streamblockchannel); await database.AddDirectoryEntryAsync(filename, metadataid.Item2, lastModified); }
/// <summary> /// Adds a file to the output, /// </summary> /// <param name="filename">The name of the file to record</param> /// <param name="lastModified">The value of the lastModified timestamp</param> /// <param name="hashlist">The list of hashes that make up the file</param> /// <param name="size">The size of the file</param> /// <param name="fragmentoffset">The offset into a fragment block where the last few bytes are stored</param> /// <param name="metadata">A lookup table with various metadata values describing the file</param> private bool AddSymlinkToOutput(string filename, DateTime lastModified, IMetahash meta) { long metadataid; bool r = false; if (meta.Size > m_blocksize) throw new InvalidDataException(string.Format("Too large metadata, cannot handle more than {0} bytes", m_blocksize)); r |= AddBlockToOutput(meta.Hash, meta.Blob, 0, (int)meta.Size, CompressionHint.Default, false); r |= m_database.AddMetadataset(meta.Hash, meta.Size, out metadataid, m_transaction); m_database.AddSymlinkEntry(filename, metadataid, lastModified, m_transaction); return r; }
/// <summary> /// Adds a file to the output, /// </summary> /// <param name="filename">The name of the file to record</param> /// <param name="lastModified">The value of the lastModified timestamp</param> /// <param name="hashlist">The list of hashes that make up the file</param> /// <param name="size">The size of the file</param> /// <param name="fragmentoffset">The offset into a fragment block where the last few bytes are stored</param> /// <param name="metadata">A lookup table with various metadata values describing the file</param> private void AddFileToOutput(string filename, long size, DateTime lastmodified, IMetahash metadata, IEnumerable<string> hashlist, string filehash, IEnumerable<string> blocklisthashes) { long metadataid; long blocksetid; if (metadata.Size > m_blocksize) throw new InvalidDataException(string.Format("Too large metadata, cannot handle more than {0} bytes", m_blocksize)); AddBlockToOutput(metadata.Hash, metadata.Blob, 0, (int)metadata.Size, CompressionHint.Default, false); m_database.AddMetadataset(metadata.Hash, metadata.Size, out metadataid, m_transaction); m_database.AddBlockset(filehash, size, m_blocksize, hashlist, blocklisthashes, out blocksetid, m_transaction); m_database.AddFile(filename, lastmodified, blocksetid, metadataid, m_transaction); }