From 1bb4c9066e5f6ef9748341dbfa119bcd1d3e73e4 Mon Sep 17 00:00:00 2001 From: schinagl Date: Thu, 10 Feb 2022 22:27:07 +0100 Subject: [PATCH 1/4] Solves to problem of winfile following reparse point during deletion of trees and causing ahrm to linked directories --- src/wfcopy.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/wfcopy.c b/src/wfcopy.c index 82c63a5e..7c7a2516 100644 --- a/src/wfcopy.c +++ b/src/wfcopy.c @@ -1442,6 +1442,12 @@ GetNextPair(PCOPYROOT pcr, LPTSTR pFrom, if (pcr->bFastMove) goto FastMoveSkipDir; #endif + // Check if we should skip an entry because it was e.g. an reparse point + if (pDTA->fd.dwFileAttributes & ATTR_SYMBOLIC) { + pDTA->fd.dwFileAttributes &= ~ATTR_SYMBOLIC; + goto SkipThisFile; + } + pcr->cDepth++; pDTA++; @@ -1685,7 +1691,14 @@ GetNextPair(PCOPYROOT pcr, LPTSTR pFrom, goto ReturnPair; } - // + // Skip reparse points + if (dwFunc == FUNC_DELETE && pDTA->fd.dwFileAttributes & ATTR_REPARSE_POINT) { + pcr->fRecurse = FALSE; + dwOp = OPER_RMDIR; + goto ReturnPair; + } + + // // Directory: operation is recursive. // pcr->fRecurse = TRUE; @@ -2723,7 +2736,16 @@ WFMoveCopyDriverThread(LPVOID lpParameter) goto CancelWholeOperation; } #endif - break; + + // Check if we came a long a reparse point + dwAttr = GetFileAttributes(szSource); + if (dwAttr & ATTR_REPARSE_POINT) { + // Yes, lets unlink it, but signal GetNextPair() that it should not crawl down the reparse point. + // We are using ATTR_SYMBOLIC to flag Junctions and Symbolic Links here + ret = RMDir(szSource); + pDTA->fd.dwFileAttributes |= ATTR_SYMBOLIC; + } + break; case IDNO: case IDCANCEL: From f22b500daf9d8a0e2133dbe8e32b76e43644f9f3 Mon Sep 17 00:00:00 2001 From: schinagl Date: Tue, 15 Feb 2022 18:57:38 +0100 Subject: [PATCH 2/4] Also skip one entry in the destination. Not needed during deletion, because there is no destination during delete. --- src/wfcopy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wfcopy.c b/src/wfcopy.c index 7c7a2516..9dc9475c 100644 --- a/src/wfcopy.c +++ b/src/wfcopy.c @@ -1445,6 +1445,7 @@ GetNextPair(PCOPYROOT pcr, LPTSTR pFrom, // Check if we should skip an entry because it was e.g. an reparse point if (pDTA->fd.dwFileAttributes & ATTR_SYMBOLIC) { pDTA->fd.dwFileAttributes &= ~ATTR_SYMBOLIC; + RemoveLast(pcr->szDest); goto SkipThisFile; } From 3329aebf0e4d44786d007a2b8482cbd83668cc04 Mon Sep 17 00:00:00 2001 From: schinagl Date: Thu, 24 Feb 2022 07:04:40 +0100 Subject: [PATCH 3/4] Adapt to #297. This makes the situation much easier --- src/wfcopy.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/wfcopy.c b/src/wfcopy.c index 9dc9475c..dfd6ccee 100644 --- a/src/wfcopy.c +++ b/src/wfcopy.c @@ -1443,8 +1443,7 @@ GetNextPair(PCOPYROOT pcr, LPTSTR pFrom, goto FastMoveSkipDir; #endif // Check if we should skip an entry because it was e.g. an reparse point - if (pDTA->fd.dwFileAttributes & ATTR_SYMBOLIC) { - pDTA->fd.dwFileAttributes &= ~ATTR_SYMBOLIC; + if (pDTA->fd.dwFileAttributes & ( ATTR_SYMBOLIC | ATTR_JUNCTION) ) { RemoveLast(pcr->szDest); goto SkipThisFile; } @@ -1693,7 +1692,7 @@ GetNextPair(PCOPYROOT pcr, LPTSTR pFrom, } // Skip reparse points - if (dwFunc == FUNC_DELETE && pDTA->fd.dwFileAttributes & ATTR_REPARSE_POINT) { + if (dwFunc == FUNC_DELETE && pDTA->fd.dwFileAttributes & (ATTR_SYMBOLIC | ATTR_JUNCTION)) { pcr->fRecurse = FALSE; dwOp = OPER_RMDIR; goto ReturnPair; @@ -2738,13 +2737,10 @@ WFMoveCopyDriverThread(LPVOID lpParameter) } #endif - // Check if we came a long a reparse point - dwAttr = GetFileAttributes(szSource); - if (dwAttr & ATTR_REPARSE_POINT) { - // Yes, lets unlink it, but signal GetNextPair() that it should not crawl down the reparse point. - // We are using ATTR_SYMBOLIC to flag Junctions and Symbolic Links here + // Check if we came a long a junction or symbolic link + if (pDTA->fd.dwFileAttributes & (ATTR_SYMBOLIC | ATTR_JUNCTION)) { + // Just unlink it ret = RMDir(szSource); - pDTA->fd.dwFileAttributes |= ATTR_SYMBOLIC; } break; From e9cd9da93f475b6902f0a87c90aeb049c558eb48 Mon Sep 17 00:00:00 2001 From: Hermann Schinagl Date: Sun, 27 Feb 2022 19:52:53 +0100 Subject: [PATCH 4/4] Don't follow Reparse Points by using OPER_RMDIR during delete --- src/wfcopy.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/wfcopy.c b/src/wfcopy.c index dfd6ccee..edad5019 100644 --- a/src/wfcopy.c +++ b/src/wfcopy.c @@ -1445,7 +1445,8 @@ GetNextPair(PCOPYROOT pcr, LPTSTR pFrom, // Check if we should skip an entry because it was e.g. an reparse point if (pDTA->fd.dwFileAttributes & ( ATTR_SYMBOLIC | ATTR_JUNCTION) ) { RemoveLast(pcr->szDest); - goto SkipThisFile; + dwOp = OPER_RMDIR; + goto ReturnPair; } pcr->cDepth++; @@ -1691,7 +1692,7 @@ GetNextPair(PCOPYROOT pcr, LPTSTR pFrom, goto ReturnPair; } - // Skip reparse points + // Return reparse point and delete it via OPER_RMDIR if (dwFunc == FUNC_DELETE && pDTA->fd.dwFileAttributes & (ATTR_SYMBOLIC | ATTR_JUNCTION)) { pcr->fRecurse = FALSE; dwOp = OPER_RMDIR; @@ -2736,12 +2737,6 @@ WFMoveCopyDriverThread(LPVOID lpParameter) goto CancelWholeOperation; } #endif - - // Check if we came a long a junction or symbolic link - if (pDTA->fd.dwFileAttributes & (ATTR_SYMBOLIC | ATTR_JUNCTION)) { - // Just unlink it - ret = RMDir(szSource); - } break; case IDNO: