[PATCH 4/4] [programs\xcopy] Add support for xcopy /k
Jason Edmeades
us at edmeades.me.uk
Wed Jul 4 16:08:41 CDT 2018
Fixes bug#40706
xcopy should remove read only permissions from the destination file unless the
/k option is supplied.
Signed-off-by: Jason Edmeades <us at edmeades.me.uk>
---
programs/xcopy/tests/xcopy.c | 25 +++++++++++++++++++++++++
programs/xcopy/xcopy.c | 25 ++++++++++++++++++-------
programs/xcopy/xcopy.h | 1 +
programs/xcopy/xcopy.rc | 1 +
4 files changed, 45 insertions(+), 7 deletions(-)
diff --git a/programs/xcopy/tests/xcopy.c b/programs/xcopy/tests/xcopy.c
index 94cede6f67..17b4406b74 100644
--- a/programs/xcopy/tests/xcopy.c
+++ b/programs/xcopy/tests/xcopy.c
@@ -108,6 +108,30 @@ static void test_parms_syntax(void)
RemoveDirectoryA("xcopytest2");
}
+static void test_keep_attributes(void)
+{
+ DWORD rc;
+
+ SetFileAttributesA("xcopy1", FILE_ATTRIBUTE_READONLY);
+
+ rc = runcmd("xcopy xcopy1 xcopytest");
+ ok(rc == 0, "xcopy failed to copy read only file\n");
+ ok((GetFileAttributesA("xcopytest\\xcopy1") & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY,
+ "xcopy should not have copied file permissions\n");
+ SetFileAttributesA("xcopytest\\xcopy1", FILE_ATTRIBUTE_NORMAL);
+ DeleteFileA("xcopytest\\xcopy1");
+
+ rc = runcmd("xcopy /K xcopy1 xcopytest");
+ ok(rc == 0, "xcopy failed to copy read only file with /k\n");
+ ok((GetFileAttributesA("xcopytest\\xcopy1") & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY,
+ "xcopy did not keep file permissions\n");
+ SetFileAttributesA("xcopytest\\xcopy1", FILE_ATTRIBUTE_NORMAL);
+ DeleteFileA("xcopytest\\xcopy1");
+
+ SetFileAttributesA("xcopy1", FILE_ATTRIBUTE_NORMAL);
+
+ }
+
START_TEST(xcopy)
{
char tmpdir[MAX_PATH];
@@ -130,6 +154,7 @@ START_TEST(xcopy)
test_date_format();
test_parms_syntax();
+ test_keep_attributes();
DeleteFileA("xcopy1");
RemoveDirectoryA("xcopytest");
diff --git a/programs/xcopy/xcopy.c b/programs/xcopy/xcopy.c
index e380cde226..cdf0bdfb26 100644
--- a/programs/xcopy/xcopy.c
+++ b/programs/xcopy/xcopy.c
@@ -570,15 +570,25 @@ static int XCOPY_DoCopy(WCHAR *srcstem, WCHAR *srcspec,
ret = RC_WRITEERROR;
goto cleanup;
}
- }
+ } else {
- /* If /M supplied, remove the archive bit after successful copy */
- if (!skipFile) {
- if ((srcAttribs & FILE_ATTRIBUTE_ARCHIVE) &&
- (flags & OPT_REMOVEARCH)) {
- SetFileAttributesW(copyFrom, (srcAttribs & ~FILE_ATTRIBUTE_ARCHIVE));
+ if (!skipFile) {
+ /* If keeping attributes, update the destination attributes
+ otherwise remove the read only attribute */
+ if (flags & OPT_KEEPATTRS) {
+ SetFileAttributesW(copyTo, srcAttribs | FILE_ATTRIBUTE_ARCHIVE);
+ } else {
+ SetFileAttributesW(copyTo,
+ (GetFileAttributesW(copyTo) & ~FILE_ATTRIBUTE_READONLY));
+ }
+
+ /* If /M supplied, remove the archive bit after successful copy */
+ if ((srcAttribs & FILE_ATTRIBUTE_ARCHIVE) &&
+ (flags & OPT_REMOVEARCH)) {
+ SetFileAttributesW(copyFrom, (srcAttribs & ~FILE_ATTRIBUTE_ARCHIVE));
+ }
+ filesCopied++;
}
- filesCopied++;
}
}
}
@@ -764,6 +774,7 @@ static int XCOPY_ParseCommandLine(WCHAR *suppliedsource,
case 'N': flags |= OPT_SHORTNAME; break;
case 'U': flags |= OPT_MUSTEXIST; break;
case 'R': flags |= OPT_REPLACEREAD; break;
+ case 'K': flags |= OPT_KEEPATTRS; break;
case 'H': flags |= OPT_COPYHIDSYS; break;
case 'C': flags |= OPT_IGNOREERRORS; break;
case 'P': flags |= OPT_SRCPROMPT; break;
diff --git a/programs/xcopy/xcopy.h b/programs/xcopy/xcopy.h
index 3e9644efe8..9c6ee1176f 100644
--- a/programs/xcopy/xcopy.h
+++ b/programs/xcopy/xcopy.h
@@ -48,6 +48,7 @@
#define OPT_EXCLUDELIST 0x00020000
#define OPT_DATERANGE 0x00040000
#define OPT_DATENEWER 0x00080000
+#define OPT_KEEPATTRS 0x00100000
#define MAXSTRING 8192
diff --git a/programs/xcopy/xcopy.rc b/programs/xcopy/xcopy.rc
index fac3519175..e303f35bdd 100644
--- a/programs/xcopy/xcopy.rc
+++ b/programs/xcopy/xcopy.rc
@@ -74,6 +74,7 @@ Where:\n\
[/A] Only copy files with archive attribute set.\n\
[/M] Only copy files with archive attribute set, removes the\n\
\tarchive attribute.\n\
+[/K] Copy file attributes, without this attributes are not preserved.\n\
[/D | /D:m-d-y] Copy new files or those modified after the supplied date.\n\
\t\tIf no date is supplied, only copy if destination is older\n\
\t\tthan source.\n\n"
--
2.17.1
More information about the wine-devel
mailing list