From: Joe Souza jsouza@yahoo.com
--- programs/xcopy/xcopy.c | 54 +++++++++++++++++++++++++++++++++-------- programs/xcopy/xcopy.h | 1 + programs/xcopy/xcopy.rc | 1 + 3 files changed, 46 insertions(+), 10 deletions(-)
diff --git a/programs/xcopy/xcopy.c b/programs/xcopy/xcopy.c index 77518fc56b2..5b1f2f3264c 100644 --- a/programs/xcopy/xcopy.c +++ b/programs/xcopy/xcopy.c @@ -325,6 +325,35 @@ static BOOL XCOPY_ProcessExcludeList(WCHAR* parms) { return FALSE; }
+/* ========================================================================= + * XCOPY_IsSameFile + * + * Checks if the two paths reference to the same file. + * Copied from WCMD builtins.c, and tab-adjusted. + * ========================================================================= */ +static BOOL XCOPY_IsSameFile(const WCHAR *name1, const WCHAR *name2) +{ + BOOL ret = FALSE; + HANDLE file1 = INVALID_HANDLE_VALUE, file2 = INVALID_HANDLE_VALUE; + BY_HANDLE_FILE_INFORMATION info1, info2; + + file1 = CreateFileW(name1, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + if (file1 != INVALID_HANDLE_VALUE && GetFileInformationByHandle(file1, &info1)) { + file2 = CreateFileW(name2, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + if (file2 != INVALID_HANDLE_VALUE && GetFileInformationByHandle(file2, &info2)) { + ret = info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber + && info1.nFileIndexHigh == info2.nFileIndexHigh + && info1.nFileIndexLow == info2.nFileIndexLow; + } + } + + if (file1 != INVALID_HANDLE_VALUE) + CloseHandle(file1); + if (file2 != INVALID_HANDLE_VALUE) + CloseHandle(file2); + return ret; +} + /* ========================================================================= XCOPY_DoCopy - Recursive function to copy files based on input parms of a stem and a spec @@ -491,7 +520,9 @@ static int XCOPY_DoCopy(WCHAR *srcstem, WCHAR *srcspec, }
if (!skipFile && - destAttribs != INVALID_FILE_ATTRIBUTES && !(flags & OPT_NOPROMPT)) { + destAttribs != INVALID_FILE_ATTRIBUTES && !(flags & OPT_NOPROMPT) && + !XCOPY_IsSameFile(copyFrom, copyTo)) { + DWORD count; char answer[10]; BOOL answered = FALSE; @@ -526,7 +557,7 @@ static int XCOPY_DoCopy(WCHAR *srcstem, WCHAR *srcspec,
/* Output a status message */ if (!skipFile) { - if (!(flags & OPT_QUIET)) { + if (!(flags & OPT_QUIET) && !(flags & OPT_SRCPROMPT)) { if (flags & OPT_FULL) XCOPY_wprintf(L"%1 -> %2\n", copyFrom, copyTo); else @@ -544,18 +575,21 @@ static int XCOPY_DoCopy(WCHAR *srcstem, WCHAR *srcspec, if (flags & OPT_SIMULATE || flags & OPT_NOCOPY) { /* Skip copy */ } else if (CopyFileW(copyFrom, copyTo, FALSE) == 0) { - - DWORD error = GetLastError(); - XCOPY_wprintf(XCOPY_LoadMessage(STRING_COPYFAIL), - copyFrom, copyTo, error); - XCOPY_FailMessage(error); - skipFile = TRUE; - if (!(flags & OPT_IGNOREERRORS)) { + if (XCOPY_IsSameFile(copyFrom, copyTo)) { + XCOPY_wprintf(XCOPY_LoadMessage(STRING_NOCOPYTOSELF)); ret = RC_WRITEERROR; + } else { + DWORD error = GetLastError(); + XCOPY_wprintf(XCOPY_LoadMessage(STRING_COPYFAIL), + copyFrom, copyTo, error); + XCOPY_FailMessage(error); + + if (!(flags & OPT_IGNOREERRORS)) { + ret = RC_WRITEERROR; + } } } else { - if (!skipFile) { /* If keeping attributes, update the destination attributes otherwise remove the read only attribute */ diff --git a/programs/xcopy/xcopy.h b/programs/xcopy/xcopy.h index 1ed9e20c45b..70b0935ba2c 100644 --- a/programs/xcopy/xcopy.h +++ b/programs/xcopy/xcopy.h @@ -69,3 +69,4 @@ #define STRING_FILE_CHAR 115 #define STRING_DIR_CHAR 116 #define STRING_HELP 117 +#define STRING_NOCOPYTOSELF 118 diff --git a/programs/xcopy/xcopy.rc b/programs/xcopy/xcopy.rc index c61e4da88fd..ae276c6b876 100644 --- a/programs/xcopy/xcopy.rc +++ b/programs/xcopy/xcopy.rc @@ -79,4 +79,5 @@ Where:\n\ \t\tIf no date is supplied, only copy if destination is older\n\ \t\tthan source.\n\n"
+ STRING_NOCOPYTOSELF, "File cannot be copied onto itself.\n" }