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();
- }
}
}