summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2019-01-09 15:47:43 +0100
committerCorinna Vinschen <corinna@vinschen.de>2019-01-09 15:47:43 +0100
commitec457e0351eee30c0d7319524e6a1a36f94dfb35 (patch)
tree1bfda8e86e2cc454284a05880c0bf8711858b604
parent15094d5d0135db0de71d02472a167904bef53cf7 (diff)
downloadcygnal-ec457e0351eee30c0d7319524e6a1a36f94dfb35.tar.gz
cygnal-ec457e0351eee30c0d7319524e6a1a36f94dfb35.tar.bz2
cygnal-ec457e0351eee30c0d7319524e6a1a36f94dfb35.zip
Cygwin: rename: use FILE_RENAME_POSIX_SEMANTICS if available
starting with W10 1709 on local NTFS drives Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
-rw-r--r--winsup/cygwin/release/2.12.04
-rw-r--r--winsup/cygwin/syscalls.cc30
-rw-r--r--winsup/doc/new-features.xml6
3 files changed, 36 insertions, 4 deletions
diff --git a/winsup/cygwin/release/2.12.0 b/winsup/cygwin/release/2.12.0
index 81a55b58d..b77278238 100644
--- a/winsup/cygwin/release/2.12.0
+++ b/winsup/cygwin/release/2.12.0
@@ -37,6 +37,10 @@ What changed:
Deleting an in-use file now actually removes the file, rather than moving
it to the recycler bin.
+- Use the new POSIX rename semantics on NTFS starting with Windows 10 1709.
+ Renaming a file to another in-use file now actually removes the other file,
+ rather than moving it to the recycler bin.
+
- open(..., O_TMPFILE) now moves the file to the trash bin immediately,
to free the parent directory.
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 78ac44bdc..4f91f4b48 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -2216,6 +2216,7 @@ rename2 (const char *oldpath, const char *newpath, unsigned int at2flags)
path_conv oldpc, newpc, new2pc, *dstpc, *removepc = NULL;
bool old_dir_requested = false, new_dir_requested = false;
bool old_explicit_suffix = false, new_explicit_suffix = false;
+ bool use_posix_semantics;
bool noreplace = at2flags & RENAME_NOREPLACE;
size_t olen, nlen;
bool equal_path;
@@ -2511,10 +2512,18 @@ rename2 (const char *oldpath, const char *newpath, unsigned int at2flags)
__leave;
}
+ /* POSIX semantics only on local NTFS drives. */
+ use_posix_semantics = wincap.has_posix_file_info ()
+ && !oldpc.isremote ()
+ && oldpc.fs_is_ntfs ();
+
/* Opening the file must be part of the transaction. It's not sufficient
to call only NtSetInformationFile under the transaction. Therefore we
- have to start the transaction here, if necessary. */
- if ((dstpc->fs_flags () & FILE_SUPPORTS_TRANSACTIONS)
+ have to start the transaction here, if necessary. Don't start
+ transaction on W10 1709 or later on local NTFS. Use POSIX semantics
+ instead. */
+ if (!use_posix_semantics
+ && (dstpc->fs_flags () & FILE_SUPPORTS_TRANSACTIONS)
&& (dstpc->isdir ()
|| (!removepc && dstpc->has_attribute (FILE_ATTRIBUTE_READONLY))))
start_transaction (old_trans, trans);
@@ -2578,6 +2587,9 @@ rename2 (const char *oldpath, const char *newpath, unsigned int at2flags)
__leave;
}
+ if (use_posix_semantics)
+ goto skip_pre_W10_checks;
+
/* Renaming a dir to another, existing dir fails always, even if
ReplaceIfExists is set to TRUE and the existing dir is empty. So
we have to remove the destination dir first. This also covers the
@@ -2619,6 +2631,8 @@ rename2 (const char *oldpath, const char *newpath, unsigned int at2flags)
}
}
+skip_pre_W10_checks:
+
/* SUSv3: If the old argument and the new argument resolve to the same
existing file, rename() shall return successfully and perform no
other action.
@@ -2666,7 +2680,13 @@ rename2 (const char *oldpath, const char *newpath, unsigned int at2flags)
__leave;
}
pfri = (PFILE_RENAME_INFORMATION) tp.w_get ();
- pfri->ReplaceIfExists = !noreplace;
+ if (use_posix_semantics)
+ pfri->Flags = noreplace ? 0
+ : (FILE_RENAME_REPLACE_IF_EXISTS
+ | FILE_RENAME_POSIX_SEMANTICS
+ | FILE_RENAME_IGNORE_READONLY_ATTRIBUTE);
+ else
+ pfri->ReplaceIfExists = !noreplace;
pfri->RootDirectory = NULL;
pfri->FileNameLength = dstpc->get_nt_native_path ()->Length;
memcpy (&pfri->FileName, dstpc->get_nt_native_path ()->Buffer,
@@ -2677,7 +2697,9 @@ rename2 (const char *oldpath, const char *newpath, unsigned int at2flags)
ERROR_ALREADY_EXISTS ==> Cygwin error EEXIST. */
status = NtSetInformationFile (fh, &io, pfri,
sizeof *pfri + pfri->FileNameLength,
- FileRenameInformation);
+ use_posix_semantics
+ ? FileRenameInformationEx
+ : FileRenameInformation);
/* This happens if the access rights don't allow deleting the destination.
Even if the handle to the original file is opened with BACKUP
and/or RECOVERY, these flags don't apply to the destination of the
diff --git a/winsup/doc/new-features.xml b/winsup/doc/new-features.xml
index f84a9c443..6af7270f9 100644
--- a/winsup/doc/new-features.xml
+++ b/winsup/doc/new-features.xml
@@ -55,6 +55,12 @@ clock_setres is a no-op now.
</para></listitem>
<listitem><para>
+Use the new POSIX rename semantics on NTFS starting with Windows 10
+1709. Renaming a file to another in-use file now actually removes the
+other file, rather than moving it to the recycler bin.
+</para></listitem>
+
+<listitem><para>
Use the new POSIX unlink semantics on NTFS starting with Windows 10
1709. Deleting an in-use file now actually removes the file, rather
than moving it to the recycler bin.