diff --git a/Duplicati/Library/Logging/Log.cs b/Duplicati/Library/Logging/Log.cs index 893cb8762..bebb87556 100644 --- a/Duplicati/Library/Logging/Log.cs +++ b/Duplicati/Library/Logging/Log.cs @@ -214,6 +214,19 @@ namespace Duplicati.Library.Logging WriteMessage(LogMessageType.Verbose, tag, id, null, message, arguments); } + /// + /// Writes a verbose message to the current log destination + /// + /// The message to write + /// The tag-type for this message + /// The message id + /// The exception to log + /// The message format arguments + public static void WriteVerboseMessage(string tag, string id, Exception ex, string message, params object[] arguments) + { + WriteMessage(LogMessageType.Verbose, tag, id, ex, message, arguments); + } + /// /// Writes a profiling message to the current log destination /// diff --git a/Duplicati/Library/Main/Operation/Backup/FileEnumerationProcess.cs b/Duplicati/Library/Main/Operation/Backup/FileEnumerationProcess.cs index 0e4743230..5dc14ae79 100644 --- a/Duplicati/Library/Main/Operation/Backup/FileEnumerationProcess.cs +++ b/Duplicati/Library/Main/Operation/Backup/FileEnumerationProcess.cs @@ -82,7 +82,8 @@ namespace Duplicati.Library.Main.Operation.Backup } else { - bool AttributeFilter(string root, string path, FileAttributes attr) => AttributeFilterAsync(root, path, attr, snapshot, sourcefilter, hardlinkPolicy, symlinkPolicy, hardlinkmap, attributeFilter, enumeratefilter, ignorenames, mixinqueue).WaitForTask().Result; + Library.Utility.Utility.EnumerationFilterDelegate AttributeFilter = (root, path, attr) => + AttributeFilterAsync(root, path, attr, snapshot, sourcefilter, hardlinkPolicy, symlinkPolicy, hardlinkmap, attributeFilter, enumeratefilter, ignorenames, mixinqueue).WaitForTask().Result; if (journalService != null) { @@ -90,9 +91,9 @@ namespace Duplicati.Library.Main.Operation.Backup sources = journalService.GetModifiedSources(AttributeFilter); } - worklist = snapshot.EnumerateFilesAndFolders(sources, AttributeFilter, (rootpath, path, ex) => + worklist = snapshot.EnumerateFilesAndFolders(sources, AttributeFilter, (rootpath, errorpath, ex) => { - Logging.Log.WriteWarningMessage(FILTER_LOGTAG, "FileAccessError", ex, "Error reported while accessing file: {0}", path); + Logging.Log.WriteWarningMessage(FILTER_LOGTAG, "FileAccessError", ex, "Error reported while accessing file: {0}", errorpath); }); } diff --git a/Duplicati/Library/Snapshots/LinuxSnapshot.cs b/Duplicati/Library/Snapshots/LinuxSnapshot.cs index b9dc71130..7faef2f8e 100644 --- a/Duplicati/Library/Snapshots/LinuxSnapshot.cs +++ b/Duplicati/Library/Snapshots/LinuxSnapshot.cs @@ -34,6 +34,14 @@ namespace Duplicati.Library.Snapshots /// public sealed class LinuxSnapshot : SnapshotBase { + /// + /// The tag used for logging messages + /// + public static readonly string LOGTAG = Logging.Log.LogTagFromType(); + + /// + /// Helper to have access to the System.IO calls without the interface layer + /// private static SystemIOLinux SYS_IO = new SystemIOLinux(); /// @@ -85,9 +93,9 @@ namespace Duplicati.Library.Snapshots { Dispose(); } - catch + catch (Exception ex) { - // ignored + Logging.Log.WriteVerboseMessage(LOGTAG, "SnapshotCleanupError", ex, "Failed to clean up after error"); } throw; @@ -97,8 +105,6 @@ namespace Duplicati.Library.Snapshots /// protected override void Dispose(bool disposing) { - Exception exs = null; - if (m_snapShots != null) { if (disposing) @@ -107,7 +113,7 @@ namespace Duplicati.Library.Snapshots foreach(var s in m_snapShots) { try { s.Dispose(); } - catch (Exception ex) { exs = ex; } + catch (Exception ex) { Logging.Log.WriteVerboseMessage(LOGTAG, "SnapshotCloseError", ex, "Failed to close a snapshot"); } } } @@ -116,10 +122,6 @@ namespace Duplicati.Library.Snapshots } base.Dispose(disposing); - - // Report errors, if any - if (exs != null) - throw exs; } /// diff --git a/Duplicati/Library/Snapshots/USNJournal.cs b/Duplicati/Library/Snapshots/USNJournal.cs index 26da5907c..0e70c9404 100644 --- a/Duplicati/Library/Snapshots/USNJournal.cs +++ b/Duplicati/Library/Snapshots/USNJournal.cs @@ -547,6 +547,7 @@ namespace Duplicati.Library.Snapshots } } + [Serializable] public class UsnJournalSoftFailureException : Exception { public UsnJournalSoftFailureException() diff --git a/Duplicati/Library/Snapshots/UsnJournalService.cs b/Duplicati/Library/Snapshots/UsnJournalService.cs index 85960d99c..f91a12806 100644 --- a/Duplicati/Library/Snapshots/UsnJournalService.cs +++ b/Duplicati/Library/Snapshots/UsnJournalService.cs @@ -64,7 +64,7 @@ namespace Duplicati.Library.Snapshots // get filter identifying current source filter / sources configuration // ReSharper disable once PossibleMultipleEnumeration - var configHash = emitFilter.GetFilterHash() + MD5HashHelper.GetHashString(MD5HashHelper.GetHash(m_sources)); + var configHash = emitFilter.GetFilterHash() + Utility.Utility.ByteArrayAsHexString(MD5HashHelper.GetHash(m_sources)); // create lookup for journal data var journalDataDict = prevJournalData.ToDictionary(data => data.Volume); diff --git a/Duplicati/Library/Snapshots/WindowsSnapshot.cs b/Duplicati/Library/Snapshots/WindowsSnapshot.cs index 4d15ee793..b0bad5d90 100644 --- a/Duplicati/Library/Snapshots/WindowsSnapshot.cs +++ b/Duplicati/Library/Snapshots/WindowsSnapshot.cs @@ -37,6 +37,11 @@ namespace Duplicati.Library.Snapshots /// public sealed class WindowsSnapshot : SnapshotBase { + /// + /// The tag used for logging messages + /// + public static readonly string LOGTAG = Logging.Log.LogTagFromType(); + /// /// The main reference to the backup controller /// @@ -161,9 +166,9 @@ namespace Duplicati.Library.Snapshots m_mappedDrives.Add(d = new DefineDosDevice(m_volumeMap[k])); m_volumeMap[k] = Utility.Utility.AppendDirSeparator(d.Drive); } - catch + catch(Exception ex) { - // ignored + Logging.Log.WriteVerboseMessage(LOGTAG, "SubstMappingfailed", ex, "Failed to map VSS path {0} to drive", k); } } } @@ -175,9 +180,9 @@ namespace Duplicati.Library.Snapshots { Dispose(); } - catch + catch(Exception ex) { - // ignored + Logging.Log.WriteVerboseMessage(LOGTAG, "VSSCleanupOnError", ex, "Failed during VSS error cleanup"); } throw; @@ -387,7 +392,7 @@ namespace Duplicati.Library.Snapshots foreach (var kvp in m_volumeReverseMap) { - if (snapshotPath.StartsWith(kvp.Key)) + if (snapshotPath.StartsWith(kvp.Key, Utility.Utility.ClientFilenameStringComparision)) return Path.Combine(kvp.Value, snapshotPath.Substring(kvp.Key.Length)); } @@ -442,40 +447,40 @@ namespace Duplicati.Library.Snapshots m_mappedDrives = null; } } - catch + catch (Exception ex) { - // ignored - } - - try - { - m_backup?.BackupComplete(); - } - catch - { - // ignored - } + Logging.Log.WriteVerboseMessage(LOGTAG, "MappedDriveCleanupError", ex, "Failed during VSS mapped drive unmapping"); + } + + try + { + m_backup?.BackupComplete(); + } + catch (Exception ex) + { + Logging.Log.WriteVerboseMessage(LOGTAG, "VSSTerminateError", ex, "Failed to signal VSS completion"); + } try { if (m_backup != null) { foreach (var g in m_volumes.Values) - { - try - { - m_backup.DeleteSnapshot(g, false); - } - catch - { - // ignored - } + { + try + { + m_backup.DeleteSnapshot(g, false); + } + catch (Exception ex) + { + Logging.Log.WriteVerboseMessage(LOGTAG, "VSSSnapShotDeleteError", ex, "Failed to close VSS snapshot"); + } } } } - catch + catch (Exception ex) { - // ignored + Logging.Log.WriteVerboseMessage(LOGTAG, "VSSSnapShotDeleteCleanError", ex, "Failed during VSS esnapshot closing"); } if (m_backup != null) diff --git a/Duplicati/Library/Utility/FilterExpression.cs b/Duplicati/Library/Utility/FilterExpression.cs index a196cca0d..b5c04c959 100644 --- a/Duplicati/Library/Utility/FilterExpression.cs +++ b/Duplicati/Library/Utility/FilterExpression.cs @@ -352,7 +352,7 @@ namespace Duplicati.Library.Utility public string GetFilterHash() { var hash = MD5HashHelper.GetHash(m_filters.Select(x => x.Filter)); - return MD5HashHelper.GetHashString(hash); + return Utility.ByteArrayAsHexString(hash); } /// diff --git a/Duplicati/Library/Utility/JoinedFilterExpression.cs b/Duplicati/Library/Utility/JoinedFilterExpression.cs index 955129774..44501eba8 100644 --- a/Duplicati/Library/Utility/JoinedFilterExpression.cs +++ b/Duplicati/Library/Utility/JoinedFilterExpression.cs @@ -41,7 +41,7 @@ namespace Duplicati.Library.Utility public string GetFilterHash() { var hash = MD5HashHelper.GetHash(new[] {First.GetFilterHash(), Second.GetFilterHash()}); - return MD5HashHelper.GetHashString(hash); + return Utility.ByteArrayAsHexString(hash); } public bool Empty { get { return First.Empty && Second.Empty; } } diff --git a/Duplicati/Library/Utility/MD5HashHelper.cs b/Duplicati/Library/Utility/MD5HashHelper.cs index 8d82a876c..97644c6ac 100644 --- a/Duplicati/Library/Utility/MD5HashHelper.cs +++ b/Duplicati/Library/Utility/MD5HashHelper.cs @@ -18,20 +18,34 @@ // #endregion +using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; namespace Duplicati.Library.Utility { + /// + /// Helper class to compute MD5 hashes + /// public static class MD5HashHelper { + /// + /// Computes the MD5 hash of the input string + /// + /// The MD5 hash. + /// The input string. public static byte[] GetHash(string inputString) { - HashAlgorithm algorithm = MD5.Create(); //or use SHA256.Create(); - return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString)); + using(var algorithm = MD5.Create()) //or use SHA256.Create(); + return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString)); } + /// + /// Computes the MD5 hash of the input strings + /// + /// The MD5 hash. + /// The input strings. public static byte[] GetHash(IEnumerable inputStrings) { using (var md5 = MD5.Create()) @@ -46,14 +60,5 @@ namespace Duplicati.Library.Utility return md5.Hash; } } - - public static string GetHashString(byte[] hash) - { - var sb = new StringBuilder(); - foreach (var b in hash) - sb.Append(b.ToString("X2")); - - return sb.ToString(); - } } }