From b25d4b47ca165d294740c0c6cf9c90ed61580635 Mon Sep 17 00:00:00 2001 From: Daniel Gehriger Date: Thu, 6 Aug 2020 16:37:48 +0200 Subject: Enabled support for \$Extend\$Deleted special MTF folder when using USN --- Duplicati/Library/Snapshots/USNJournal.cs | 66 ++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 15 deletions(-) (limited to 'Duplicati/Library/Snapshots') diff --git a/Duplicati/Library/Snapshots/USNJournal.cs b/Duplicati/Library/Snapshots/USNJournal.cs index 111a871b3..2d6d84a78 100644 --- a/Duplicati/Library/Snapshots/USNJournal.cs +++ b/Duplicati/Library/Snapshots/USNJournal.cs @@ -86,6 +86,11 @@ namespace Duplicati.Library.Snapshots /// private SafeFileHandle m_volumeHandle; + /// + /// Determined file ref number of "\$Extend\$Deleted\" folder + /// + private ulong? m_extendDeletedRefNr = null; + /// /// Constructs a new USN helper instance /// @@ -382,7 +387,7 @@ namespace Duplicati.Library.Snapshots if (e == Win32USN.ERROR_INSUFFICIENT_BUFFER) { - bufferSize = bufferSize * 2; + bufferSize *= 2; continue; } @@ -423,13 +428,16 @@ namespace Duplicati.Library.Snapshots return null; // retry, increasing buffer size - bufferSize = bufferSize * 2; + bufferSize *= 2; } // not really a foreach: we only check the first record foreach (var rec in EnumerateRecords(entryData)) + { if (rec.UsnRecord.FileReferenceNumber == frn) return rec; + break; + } return null; } @@ -476,6 +484,31 @@ namespace Duplicati.Library.Snapshots { // parent FRN not found in look-up table, fetch it from change journal var parentRecord = GetRecordByFileRef(parentRefNr); + + if (parentRecord == null) + { + // check if this file was moved to the special \$Extend\$Deleted folder + // we do so by comparing its file name against the file reference number + if (cur.FileName.Length > 16 && cur.UsnRecord.FileReferenceNumber.ToString("X16") == cur.FileName.Substring(0, 16)) + { + // as a safety precaution, we ensure that the FileReferenceNumber for " \$Extend\$Deleted" + // determined in this way is the same for *all* files + if (!m_extendDeletedRefNr.HasValue) + { + m_extendDeletedRefNr = parentRefNr; + } + else if (m_extendDeletedRefNr.Value != parentRefNr) + throw new UsnJournalSoftFailureException(Strings.USNHelper.PathResolveError); + + pathList.Clear(); + break; + } + else + { + Debug.Assert(false); + } + } + parents = new SortedRecords(new List { parentRecord }); cache.Add(parentRefNr, parents); } @@ -490,22 +523,25 @@ namespace Duplicati.Library.Snapshots cur = parent; } - // generate full path - Debug.Assert(m_volume != null, nameof(m_volume) + " != null"); - var path = m_volume; - foreach (var r in pathList) + if (pathList.Count > 0) { - path = SystemIO.IO_WIN.PathCombine(path, r.FileName); - } + // generate full path + Debug.Assert(m_volume != null, nameof(m_volume) + " != null"); + var path = m_volume; + foreach (var r in pathList) + { + path = SystemIO.IO_WIN.PathCombine(path, r.FileName); + } - if (rec.UsnRecord.FileAttributes.HasFlag(Win32USN.FileAttributes.Directory)) - { - path = Util.AppendDirSeparator(path); - } + if (rec.UsnRecord.FileAttributes.HasFlag(Win32USN.FileAttributes.Directory)) + { + path = Util.AppendDirSeparator(path); + } - // set resolved path - rec.FullPath = path; - result.Add(rec); + // set resolved path + rec.FullPath = path; + result.Add(rec); + } } return result; -- cgit v1.2.3 From 51ce673831f4f247b4d8b7a1326d9f395cd1817e Mon Sep 17 00:00:00 2001 From: Daniel Gehriger Date: Thu, 6 Aug 2020 16:56:52 +0200 Subject: Removed debug assert --- Duplicati/Library/Snapshots/USNJournal.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'Duplicati/Library/Snapshots') diff --git a/Duplicati/Library/Snapshots/USNJournal.cs b/Duplicati/Library/Snapshots/USNJournal.cs index 2d6d84a78..f5d804933 100644 --- a/Duplicati/Library/Snapshots/USNJournal.cs +++ b/Duplicati/Library/Snapshots/USNJournal.cs @@ -485,11 +485,12 @@ namespace Duplicati.Library.Snapshots // parent FRN not found in look-up table, fetch it from change journal var parentRecord = GetRecordByFileRef(parentRefNr); - if (parentRecord == null) + if (parentRecord == null && cur.UsnRecord.Reason == Win32USN.USNReason.USN_REASON_RENAME_NEW_NAME) { // check if this file was moved to the special \$Extend\$Deleted folder // we do so by comparing its file name against the file reference number - if (cur.FileName.Length > 16 && cur.UsnRecord.FileReferenceNumber.ToString("X16") == cur.FileName.Substring(0, 16)) + if (cur.FileName.Length > 16 + && cur.UsnRecord.FileReferenceNumber.ToString("X16") == cur.FileName.Substring(0, 16)) { // as a safety precaution, we ensure that the FileReferenceNumber for " \$Extend\$Deleted" // determined in this way is the same for *all* files @@ -503,10 +504,6 @@ namespace Duplicati.Library.Snapshots pathList.Clear(); break; } - else - { - Debug.Assert(false); - } } parents = new SortedRecords(new List { parentRecord }); -- cgit v1.2.3 From 279d8d2d2c4b556028588909e65e8923cb65d73d Mon Sep 17 00:00:00 2001 From: Daniel Gehriger Date: Thu, 6 Aug 2020 17:58:19 +0200 Subject: Fixed usn reason comparison (was too severe) --- Duplicati/Library/Snapshots/USNJournal.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Duplicati/Library/Snapshots') diff --git a/Duplicati/Library/Snapshots/USNJournal.cs b/Duplicati/Library/Snapshots/USNJournal.cs index f5d804933..ef020df88 100644 --- a/Duplicati/Library/Snapshots/USNJournal.cs +++ b/Duplicati/Library/Snapshots/USNJournal.cs @@ -485,7 +485,8 @@ namespace Duplicati.Library.Snapshots // parent FRN not found in look-up table, fetch it from change journal var parentRecord = GetRecordByFileRef(parentRefNr); - if (parentRecord == null && cur.UsnRecord.Reason == Win32USN.USNReason.USN_REASON_RENAME_NEW_NAME) + if (parentRecord == null + && (cur.UsnRecord.Reason & Win32USN.USNReason.USN_REASON_RENAME_NEW_NAME) == Win32USN.USNReason.USN_REASON_RENAME_NEW_NAME) { // check if this file was moved to the special \$Extend\$Deleted folder // we do so by comparing its file name against the file reference number -- cgit v1.2.3